src/share/vm/classfile/classFileParser.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
*** old/src/share/vm/classfile/classFileParser.cpp Wed Aug 3 07:54:48 2016
--- new/src/share/vm/classfile/classFileParser.cpp Wed Aug 3 07:54:47 2016
*** 5400,5409 ****
--- 5400,5470 ----
set_klass(ik);
debug_only(ik->verify();)
}
+ // For an anonymous class that is in the null package, move it to its host class's
+ // package by prepending its host class's package name to its class name and setting
+ // its _class_name field.
+ void ClassFileParser::prepend_host_package_name(const Klass* host_klass, TRAPS) {
+ ResourceMark rm(THREAD);
+ assert(strrchr(_class_name->as_C_string(), '/') == NULL,
+ "Anonymous class should not be in a package");
+ int host_pkg_len = 0;
+ const char* host_pkg_name =
+ (const char*)InstanceKlass::package_from_name(host_klass->name(), CHECK);
+ if (host_pkg_name != NULL) {
+ char* new_anon_name =
+ NEW_RESOURCE_ARRAY(char, host_pkg_len + 1 + _class_name->utf8_length());
+ // Copy host package name and trailing /.
+ strncpy(new_anon_name, host_pkg_name, host_pkg_len);
+ new_anon_name[host_pkg_len] = '/';
+ // Append anonymous class name. The anonymous class name can contain odd
+ // characters. So, do a strncpy instead of using sprintf("%s...").
+ strncpy(new_anon_name + host_pkg_len + 1, (char *)_class_name->base(),
+ _class_name->utf8_length());
+
+ // Create a symbol and update the anonymous class name.
+ _class_name = SymbolTable::lookup(new_anon_name,
+ host_pkg_len + 1 + _class_name->utf8_length(),
+ CHECK);
+ }
+ }
+
+ // If the host class and the anonymous class are in the same package then do
+ // nothing. If the anonymous class is in the null package then move it to its
+ // host's package. If the classes are in different packages then throw an IAE
+ // exception.
+ void ClassFileParser::fix_anonymous_class_name(TRAPS) {
+ assert(_host_klass != NULL, "Expected an anonymous class");
+ const jbyte* anon_last_slash = UTF8::strrchr(_class_name->base(),
+ _class_name->utf8_length(), '/');
+ const Klass* host_klass;
+ if (_host_klass->is_objArray_klass()) {
+ host_klass = ObjArrayKlass::cast(_host_klass)->element_klass();
+ } else {
+ host_klass = _host_klass;
+ }
+ assert(host_klass->is_instance_klass(), "host klass is not an instance class");
+
+ if (anon_last_slash == NULL) { // Unnamed package
+ prepend_host_package_name(host_klass, CHECK);
+
+ } else {
+ if (!InstanceKlass::is_same_class_package(host_klass->class_loader(),
+ host_klass->name(),
+ host_klass->class_loader(),
+ _class_name)) {
+ ResourceMark rm(THREAD);
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+ err_msg("Host class %s and anonymous class %s are in different packages",
+ _host_klass->name()->as_C_string(), _class_name->as_C_string()));
+ }
+ }
+ }
+
+
ClassFileParser::ClassFileParser(ClassFileStream* stream,
Symbol* name,
ClassLoaderData* loader_data,
Handle protection_domain,
const Klass* host_klass,
*** 5679,5688 ****
--- 5740,5756 ----
_requested_name != NULL ? _requested_name->as_C_string() : "NoName"
);
return;
}
+ // if this is an anonymous class fix up its name if it's in the unnamed
+ // package. Otherwise, throw IAE if it is in a different package than
+ // its host class.
+ if (_host_klass != NULL) {
+ fix_anonymous_class_name(CHECK);
+ }
+
// Verification prevents us from creating names with dots in them, this
// asserts that that's the case.
assert(is_internal_format(_class_name), "external class name format used internally");
if (!is_internal()) {
src/share/vm/classfile/classFileParser.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File