FieldStreamBase(instanceKlassHandle klass) { _fields = klass->fields(); _constants = klass->constants(); _index = 0; _limit = klass->java_fields_count(); init_generic_signature_start_slot(); }
bool VerificationType::resolve_and_check_assignability(instanceKlassHandle klass, Symbol* name, Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object, TRAPS) { Klass* obj = SystemDictionary::resolve_or_fail( name, Handle(THREAD, klass->class_loader()), Handle(THREAD, klass->protection_domain()), true, CHECK_false); if (log_is_enabled(Debug, class, resolve)) { Verifier::trace_class_resolution(obj, klass()); } KlassHandle this_class(THREAD, obj); if (this_class->is_interface() && (!from_field_is_protected || from_name != vmSymbols::java_lang_Object())) { // If we are not trying to access a protected field or method in // java.lang.Object then, for arrays, we only allow assignability // to interfaces java.lang.Cloneable and java.io.Serializable. // Otherwise, we treat interfaces as java.lang.Object. return !from_is_array || this_class == SystemDictionary::Cloneable_klass() || this_class == SystemDictionary::Serializable_klass(); } else if (from_is_object) { Klass* from_class = SystemDictionary::resolve_or_fail( from_name, Handle(THREAD, klass->class_loader()), Handle(THREAD, klass->protection_domain()), true, CHECK_false); if (log_is_enabled(Debug, class, resolve)) { Verifier::trace_class_resolution(from_class, klass()); } return InstanceKlass::cast(from_class)->is_subclass_of(this_class()); } return false; }
// Field names and signatures are referenced via constantpool indexes. In the new class // version, the layout of the constantpool can be different, so these indexes should be // patched. void patch_indexes_for_fields(instanceKlassHandle k_h, instanceKlassHandle k_h_new) { typeArrayOop k_fields = k_h->fields(); typeArrayOop k_new_fields = k_h_new->fields(); int n_fields = k_fields->length(); for (int i = 0; i < n_fields; i += instanceKlass::next_offset) { // name and signature k_fields->short_at_put( i + instanceKlass::name_index_offset, k_new_fields->short_at(i + instanceKlass::name_index_offset) ); k_fields->short_at_put( i + instanceKlass::signature_index_offset, k_new_fields->short_at(i + instanceKlass::signature_index_offset) ); } }
KlassStream::KlassStream(instanceKlassHandle klass, bool local_only, bool classes_only) { _klass = klass; if (classes_only) { _interfaces = Universe::the_empty_system_obj_array(); } else { _interfaces = klass->transitive_interfaces(); } _interface_index = _interfaces->length(); _local_only = local_only; _classes_only = classes_only; }
instanceKlassHandle record_result(const int classpath_index, const ClassPathEntry* e, instanceKlassHandle result, TRAPS) { if (ClassLoader::add_package(_file_name, classpath_index, THREAD)) { if (DumpSharedSpaces) { result->set_shared_classpath_index(classpath_index); } return result; } else { return instanceKlassHandle(); // NULL } }
// Calls to this constructor must be proceeded by a ResourceMark // and a HandleMark JvmtiConstantPoolReconstituter(instanceKlassHandle ikh){ set_error(JVMTI_ERROR_NONE); _ikh = ikh; _cpool = constantPoolHandle(Thread::current(), ikh->constants()); _symmap = new SymbolHashMap(); _classmap = new SymbolHashMap(); _cpool_size = _cpool->hash_entries_to(_symmap, _classmap); if (_cpool_size == 0) { set_error(JVMTI_ERROR_OUT_OF_MEMORY); } else if (_cpool_size < 0) { set_error(JVMTI_ERROR_INTERNAL); } }
void CHA::process_interface(instanceKlassHandle r, GrowableArray<KlassHandle>* receivers, GrowableArray<methodHandle>* methods, symbolHandle name, symbolHandle signature) { // recursively add non-abstract implementors of interface r to receivers list assert(r->is_interface(), "should call process_class instead"); // We only store the implementors for an interface, if there is exactly one implementor klassOop k = r->implementor(); assert(k == NULL || r->nof_implementors() == 1, "inconsistent implementor list"); if (k != NULL && !methods->is_full()) { instanceKlass* kl = instanceKlass::cast(k); assert(kl->oop_is_instance(), "primitive klasses don't implement interfaces"); assert(!kl->is_interface(), "must be a real klass"); process_class(kl, receivers, methods, name, signature); } // now process all subinterfaces for (Klass* s = r->subklass(); s != NULL && !methods->is_full(); s = s->next_sibling()) { assert(s->is_interface(), "must be an interface"); instanceKlassHandle sub(s->as_klassOop()); process_interface(sub, receivers, methods, name, signature); if (methods->is_full()) break; // give up -- too many overriding methods } }
void Dictionary::add_protection_domain(int index, unsigned int hash, instanceKlassHandle klass, ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { Symbol* klass_name = klass->name(); DictionaryEntry* entry = get_entry(index, hash, klass_name, loader_data); assert(entry != NULL,"entry must be present, we just created it"); assert(protection_domain() != NULL, "real protection domain should be present"); entry->add_protection_domain(this, protection_domain()); assert(entry->contains_protection_domain(protection_domain()), "now protection domain should be present"); }
InternalFieldStream(instanceKlassHandle k): FieldStreamBase(k->fields(), k->constants(), k->java_fields_count(), 0) {}
// Relocate jsr/rets in a method. This can't be done with the rewriter // stage because it can throw other exceptions, leaving the bytecodes // pointing at constant pool cache entries. // Link and check jvmti dependencies while we're iterating over the methods. // JSR292 code calls with a different set of methods, so two entry points. void Rewriter::relocate_and_link(instanceKlassHandle this_oop, TRAPS) { objArrayHandle methods(THREAD, this_oop->methods()); relocate_and_link(this_oop, methods, THREAD); }
void Rewriter::rewrite(instanceKlassHandle klass, TRAPS) { ResourceMark rm(THREAD); Rewriter rw(klass, klass->constants(), klass->methods(), CHECK); // (That's all, folks.) }
jvmdiError compare_class_versions(instanceKlassHandle k_h_old, instanceKlassHandle k_h_new) { int i; // Check whether essential class modifiers are the same. The rest can probably differ, e.g. // why not allow substitute class to be synthetic, if it satisfies other conditions. AccessFlags old_flags = k_h_old->access_flags(); AccessFlags new_flags = k_h_new->access_flags(); if (old_flags.is_public() != new_flags.is_public() || old_flags.is_final() != new_flags.is_final() || old_flags.is_interface() != new_flags.is_interface() || old_flags.is_abstract() != new_flags.is_abstract()) { return JVMDI_ERROR_CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED; } // Check superclasses, or rather their names, since superclasses themselves can be // requested to replace if (Klass::cast(k_h_old->super())->name() != Klass::cast(k_h_new->super())->name()) { return JVMDI_ERROR_HIERARCHY_CHANGE_NOT_IMPLEMENTED; } // Check if the number, names and order of directly implemented interfaces are the same. // I think in principle we should just check if the sets of names of directly implemented // interfaces are the same, i.e. the order of declaration (which, however, if changed in the // .java file, also changes in .class file) should not matter. However, comparing sets is // technically a bit more difficult, and, more importantly, I am not sure at present that the // order of interfaces does not matter on the implementation level, i.e. that the VM does not // rely on it somewhere. objArrayOop k_interfaces = k_h_old->local_interfaces(); objArrayOop k_new_interfaces = k_h_new->local_interfaces(); int n_intfs = k_interfaces->length(); if (n_intfs != k_new_interfaces->length()) { return JVMDI_ERROR_HIERARCHY_CHANGE_NOT_IMPLEMENTED; } for (i = 0; i < n_intfs; i++) { if (Klass::cast((klassOop) k_interfaces->obj_at(i))->name() != Klass::cast((klassOop) k_new_interfaces->obj_at(i))->name()) { return JVMDI_ERROR_HIERARCHY_CHANGE_NOT_IMPLEMENTED; } } // Check if the number, names, types and order of fields declared in these classes // are the same. typeArrayOop k_old_fields = k_h_old->fields(); typeArrayOop k_new_fields = k_h_new->fields(); int n_fields = k_old_fields->length(); if (n_fields != k_new_fields->length()) { return JVMDI_ERROR_SCHEMA_CHANGE_NOT_IMPLEMENTED; } for (i = 0; i < n_fields; i += instanceKlass::next_offset) { // access if (k_old_fields->ushort_at(i + instanceKlass::access_flags_offset) != k_new_fields->ushort_at(i + instanceKlass::access_flags_offset)) { return JVMDI_ERROR_SCHEMA_CHANGE_NOT_IMPLEMENTED; } // offset if (k_old_fields->short_at(i + instanceKlass::low_offset) != k_new_fields->short_at(i + instanceKlass::low_offset) || k_old_fields->short_at(i + instanceKlass::high_offset) != k_new_fields->short_at(i + instanceKlass::high_offset)) { return JVMDI_ERROR_SCHEMA_CHANGE_NOT_IMPLEMENTED; } // name and signature jshort name_index = k_old_fields->short_at(i + instanceKlass::name_index_offset); jshort sig_index = k_old_fields->short_at(i +instanceKlass::signature_index_offset); symbolOop name_sym1 = k_h_old->constants()->symbol_at(name_index); symbolOop sig_sym1 = k_h_old->constants()->symbol_at(sig_index); name_index = k_new_fields->short_at(i + instanceKlass::name_index_offset); sig_index = k_new_fields->short_at(i + instanceKlass::signature_index_offset); symbolOop name_sym2 = k_h_new->constants()->symbol_at(name_index); symbolOop sig_sym2 = k_h_new->constants()->symbol_at(sig_index); if (name_sym1 != name_sym2 || sig_sym1 != sig_sym2) { return JVMDI_ERROR_SCHEMA_CHANGE_NOT_IMPLEMENTED; } } // Check if the number, names, signatures and order of methods declared in these classes // are the same. objArrayOop k_methods = k_h_old->methods(); objArrayOop k_new_methods = k_h_new->methods(); int n_methods = k_methods->length(); if (n_methods < k_new_methods->length()) return JVMDI_ERROR_ADD_METHOD_NOT_IMPLEMENTED; else if (n_methods > k_new_methods->length()) return JVMDI_ERROR_DELETE_METHOD_NOT_IMPLEMENTED; for (i = 0; i < n_methods; i++) { methodOop k_method = (methodOop) k_methods->obj_at(i); methodOop k_new_method = (methodOop) k_new_methods->obj_at(i); if (k_method->name() != k_new_method->name()) return JVMDI_ERROR_DELETE_METHOD_NOT_IMPLEMENTED; if (k_method->signature() != k_new_method->signature()) { return JVMDI_ERROR_DELETE_METHOD_NOT_IMPLEMENTED; } old_flags = k_method->access_flags(); new_flags = k_new_method->access_flags(); // It's probably safer to not compare the values of access_flags directly, since // some bits in them encode some implementation-specific information, e.g. // something about inlined tables. This may be different in the new version, // but should not affect method changeability. if (old_flags.is_public() != new_flags.is_public() || old_flags.is_protected() != new_flags.is_protected() || old_flags.is_private() != new_flags.is_private() || old_flags.is_static() != new_flags.is_static() || old_flags.is_final() != new_flags.is_final() || old_flags.is_synchronized() != new_flags.is_synchronized() || old_flags.is_strict() != new_flags.is_strict() || old_flags.is_interface() != new_flags.is_interface() || old_flags.is_abstract() != new_flags.is_abstract()) { return JVMDI_ERROR_METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED; } } return JVMDI_ERROR_NONE; }
jvmtiError VM_RedefineClasses::compare_class_versions(instanceKlassHandle k_h_old, instanceKlassHandle k_h_new) { int i; // Check superclasses, or rather their names, since superclasses themselves can be // requested to replace. // Check for NULL superclass first since this might be java.lang.Object if (k_h_old->super() != k_h_new->super() && (k_h_old->super() == NULL || k_h_new->super() == NULL || Klass::cast(k_h_old->super())->name() != Klass::cast(k_h_new->super())->name())) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED; } // Check if the number, names and order of directly implemented interfaces are the same. // I think in principle we should just check if the sets of names of directly implemented // interfaces are the same, i.e. the order of declaration (which, however, if changed in the // .java file, also changes in .class file) should not matter. However, comparing sets is // technically a bit more difficult, and, more importantly, I am not sure at present that the // order of interfaces does not matter on the implementation level, i.e. that the VM does not // rely on it somewhere. objArrayOop k_interfaces = k_h_old->local_interfaces(); objArrayOop k_new_interfaces = k_h_new->local_interfaces(); int n_intfs = k_interfaces->length(); if (n_intfs != k_new_interfaces->length()) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED; } for (i = 0; i < n_intfs; i++) { if (Klass::cast((klassOop) k_interfaces->obj_at(i))->name() != Klass::cast((klassOop) k_new_interfaces->obj_at(i))->name()) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED; } } // Check whether class is in the error init state. if (k_h_old->is_in_error_state()) { // TBD #5057930: special error code is needed in 1.6 return JVMTI_ERROR_INVALID_CLASS; } // Check whether class modifiers are the same. jushort old_flags = (jushort) k_h_old->access_flags().get_flags(); jushort new_flags = (jushort) k_h_new->access_flags().get_flags(); if (old_flags != new_flags) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED; } // Check if the number, names, types and order of fields declared in these classes // are the same. typeArrayOop k_old_fields = k_h_old->fields(); typeArrayOop k_new_fields = k_h_new->fields(); int n_fields = k_old_fields->length(); if (n_fields != k_new_fields->length()) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED; } for (i = 0; i < n_fields; i += instanceKlass::next_offset) { // access old_flags = k_old_fields->ushort_at(i + instanceKlass::access_flags_offset); new_flags = k_new_fields->ushort_at(i + instanceKlass::access_flags_offset); if ((old_flags ^ new_flags) & JVM_RECOGNIZED_FIELD_MODIFIERS) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED; } // offset if (k_old_fields->short_at(i + instanceKlass::low_offset) != k_new_fields->short_at(i + instanceKlass::low_offset) || k_old_fields->short_at(i + instanceKlass::high_offset) != k_new_fields->short_at(i + instanceKlass::high_offset)) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED; } // name and signature jshort name_index = k_old_fields->short_at(i + instanceKlass::name_index_offset); jshort sig_index = k_old_fields->short_at(i +instanceKlass::signature_index_offset); symbolOop name_sym1 = k_h_old->constants()->symbol_at(name_index); symbolOop sig_sym1 = k_h_old->constants()->symbol_at(sig_index); name_index = k_new_fields->short_at(i + instanceKlass::name_index_offset); sig_index = k_new_fields->short_at(i + instanceKlass::signature_index_offset); symbolOop name_sym2 = k_h_new->constants()->symbol_at(name_index); symbolOop sig_sym2 = k_h_new->constants()->symbol_at(sig_index); if (name_sym1 != name_sym2 || sig_sym1 != sig_sym2) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED; } } // Check if the number, names, signatures and order of methods declared in these classes // are the same. objArrayOop k_methods = k_h_old->methods(); objArrayOop k_new_methods = k_h_new->methods(); int n_methods = k_methods->length(); if (n_methods < k_new_methods->length()) return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED; else if (n_methods > k_new_methods->length()) return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED; for (i = 0; i < n_methods; i++) { methodOop k_method = (methodOop) k_methods->obj_at(i); methodOop k_new_method = (methodOop) k_new_methods->obj_at(i); if (k_method->name() != k_new_method->name()) return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED; if (k_method->signature() != k_new_method->signature()) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED; } old_flags = (jushort) k_method->access_flags().get_flags(); new_flags = (jushort) k_new_method->access_flags().get_flags(); if (old_flags != new_flags) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED; } } return JVMTI_ERROR_NONE; }
// Install the redefinition of a class -- // The original instanceKlass object (k_h) always represents the latest // version of the respective class. However, during class redefinition we swap // or replace much of its content with that of the instanceKlass object created // from the bytes of the redefine (k_h_new). Specifically, k_h points to the new // constantpool and methods objects, which we take from k_h_new. k_h_new, in turn, // assumes the role of the previous class version, with the old constantpool and // methods (taken from k_h) attached to it. k_h links to k_h_new to create a // linked list of class versions. void VM_RedefineClasses::redefine_single_class(jclass j_clazz, instanceKlassHandle k_h_new, TRAPS) { oop mirror = JNIHandles::resolve_non_null(j_clazz); klassOop k_oop = java_lang_Class::as_klassOop(mirror); instanceKlassHandle k_h = instanceKlassHandle(THREAD, k_oop); // Remove all breakpoints in methods of this class JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints(); jvmti_breakpoints.clearall_in_class_at_safepoint(k_oop); // Deoptimize all compiled code that depends on this class NOT_CORE(Universe::flush_evol_dependents_on(k_h)); _old_methods = k_h->methods(); _new_methods = k_h_new->methods(); _evolving_koop = k_oop; _old_constants = k_h->constants(); // flush the cached jmethodID fields for _old_methods flush_method_jmethod_id_cache(); // Patch the indexes into the constantpool from the array of fields of the evolving // class. This is required, because the layout of the new constantpool can be different, // so old indexes corresponding to field names and signatures can become invalid. patch_indexes_for_fields(k_h, k_h_new); // Make new constantpool object (and methodOops via it) point to the original class object k_h_new->constants()->set_pool_holder(k_h()); // Replace methods and constantpool k_h->set_methods(_new_methods); k_h_new->set_methods(_old_methods); // To prevent potential GCing of the old methods, // and to be able to undo operation easily. constantPoolOop old_constants = k_h->constants(); k_h->set_constants(k_h_new->constants()); k_h_new->set_constants(old_constants); // See the previous comment. check_methods_and_mark_as_old(); transfer_old_native_function_registrations(); // Replace inner_classes typeArrayOop old_inner_classes = k_h->inner_classes(); k_h->set_inner_classes(k_h_new->inner_classes()); k_h_new->set_inner_classes(old_inner_classes); // Initialize the vtable and interface table after // methods have been rewritten { ResourceMark rm(THREAD); k_h->vtable()->initialize_vtable(THREAD); // No exception can happen here k_h->itable()->initialize_itable(); } // Copy the "source file name" attribute from new class version k_h->set_source_file_name(k_h_new->source_file_name()); // Copy the "source debug extension" attribute from new class version k_h->set_source_debug_extension(k_h_new->source_debug_extension()); // Use of javac -g could be different in the old and the new if (k_h_new->access_flags().has_localvariable_table() != k_h->access_flags().has_localvariable_table()) { AccessFlags flags = k_h->access_flags(); if (k_h_new->access_flags().has_localvariable_table()) { flags.set_has_localvariable_table(); } else { flags.clear_has_localvariable_table(); } k_h->set_access_flags(flags); } // Replace class annotation fields values typeArrayOop old_class_annotations = k_h->class_annotations(); k_h->set_class_annotations(k_h_new->class_annotations()); k_h_new->set_class_annotations(old_class_annotations); // Replace fields annotation fields values objArrayOop old_fields_annotations = k_h->fields_annotations(); k_h->set_fields_annotations(k_h_new->fields_annotations()); k_h_new->set_fields_annotations(old_fields_annotations); // Replace methods annotation fields values objArrayOop old_methods_annotations = k_h->methods_annotations(); k_h->set_methods_annotations(k_h_new->methods_annotations()); k_h_new->set_methods_annotations(old_methods_annotations); // Replace methods parameter annotation fields values objArrayOop old_methods_parameter_annotations = k_h->methods_parameter_annotations(); k_h->set_methods_parameter_annotations(k_h_new->methods_parameter_annotations()); k_h_new->set_methods_parameter_annotations(old_methods_parameter_annotations); // Replace methods default annotation fields values objArrayOop old_methods_default_annotations = k_h->methods_default_annotations(); k_h->set_methods_default_annotations(k_h_new->methods_default_annotations()); k_h_new->set_methods_default_annotations(old_methods_default_annotations); // Replace major version number of class file u2 old_major_version = k_h->major_version(); k_h->set_major_version(k_h_new->major_version()); k_h_new->set_major_version(old_major_version); // Replace CP indexes for class and name+type of enclosing method u2 old_class_idx = k_h->enclosing_method_class_index(); u2 old_method_idx = k_h->enclosing_method_method_index(); k_h->set_enclosing_method_indices(k_h_new->enclosing_method_class_index(), k_h_new->enclosing_method_method_index()); k_h_new->set_enclosing_method_indices(old_class_idx, old_method_idx); // Maintain a linked list of versions of this class. // List is in ascending age order. Current version (k_h) is the head. if (k_h->has_previous_version()) { k_h_new->set_previous_version(k_h->previous_version()); } k_h->set_previous_version(k_h_new); // Adjust constantpool caches and vtables for all classes // that reference methods of the evolved class. SystemDictionary::classes_do(adjust_cpool_cache_and_vtable); k_h->set_rewritten_by_redefine(true); }
AllFieldStream(instanceKlassHandle k): FieldStreamBase(k->fields(), k->constants()) {}
// Some recursive calls from the verifier to the name resolver // can cause the current class to be re-verified and rewritten. // If this happens, the original verification should not continue, // because constant pool indexes will have changed. // The rewriter is preceded by the verifier. If the verifier throws // an error, rewriting is prevented. Also, rewriting always precedes // bytecode execution or compilation. Thus, is_rewritten implies // that a class has been verified and prepared for execution. bool was_recursively_verified() { return _klass->is_rewritten(); }
// called during initial loading of a shared class instanceKlassHandle KlassFactory::check_shared_class_file_load_hook( instanceKlassHandle ik, Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS) { #if INCLUDE_CDS && INCLUDE_JVMTI assert(ik.not_null(), "sanity"); assert(ik()->is_shared(), "expecting a shared class"); if (JvmtiExport::should_post_class_file_load_hook()) { assert(THREAD->is_Java_thread(), "must be JavaThread"); // Post the CFLH JvmtiCachedClassFileData* cached_class_file = NULL; JvmtiCachedClassFileData* archived_class_data = ik->get_archived_class_data(); assert(archived_class_data != NULL, "shared class has no archived class data"); unsigned char* ptr = VM_RedefineClasses::get_cached_class_file_bytes(archived_class_data); unsigned char* end_ptr = ptr + VM_RedefineClasses::get_cached_class_file_len(archived_class_data); unsigned char* old_ptr = ptr; JvmtiExport::post_class_file_load_hook(class_name, class_loader, protection_domain, &ptr, &end_ptr, &cached_class_file); if (old_ptr != ptr) { // JVMTI agent has modified class file data. // Set new class file stream using JVMTI agent modified class file data. ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader()); int path_index = ik->shared_classpath_index(); SharedClassPathEntry* ent = (SharedClassPathEntry*)FileMapInfo::shared_classpath(path_index); ClassFileStream* stream = new ClassFileStream(ptr, end_ptr - ptr, ent == NULL ? NULL : ent->_name, ClassFileStream::verify); ClassFileParser parser(stream, class_name, loader_data, protection_domain, NULL, NULL, ClassFileParser::BROADCAST, // publicity level CHECK_NULL); instanceKlassHandle new_ik = parser.create_instance_klass(true /* changed_by_loadhook */, CHECK_NULL); if (cached_class_file != NULL) { new_ik->set_cached_class_file(cached_class_file); } if (class_loader.is_null()) { ResourceMark rm; ClassLoader::add_package(class_name->as_C_string(), path_index, THREAD); } return new_ik; } } #endif return NULL; }