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