Path: blob/master/src/hotspot/share/classfile/klassFactory.cpp
40949 views
/*1* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "cds/filemap.hpp"26#include "classfile/classFileParser.hpp"27#include "classfile/classFileStream.hpp"28#include "classfile/classLoader.hpp"29#include "classfile/classLoaderData.hpp"30#include "classfile/classLoaderData.inline.hpp"31#include "classfile/classLoadInfo.hpp"32#include "classfile/klassFactory.hpp"33#include "memory/resourceArea.hpp"34#include "prims/jvmtiEnvBase.hpp"35#include "prims/jvmtiRedefineClasses.hpp"36#include "runtime/arguments.hpp"37#include "runtime/handles.inline.hpp"38#include "utilities/macros.hpp"39#if INCLUDE_JFR40#include "jfr/support/jfrKlassExtension.hpp"41#endif424344// called during initial loading of a shared class45InstanceKlass* KlassFactory::check_shared_class_file_load_hook(46InstanceKlass* ik,47Symbol* class_name,48Handle class_loader,49Handle protection_domain,50const ClassFileStream *cfs,51TRAPS) {52#if INCLUDE_CDS && INCLUDE_JVMTI53assert(ik != NULL, "sanity");54assert(ik->is_shared(), "expecting a shared class");55if (JvmtiExport::should_post_class_file_load_hook()) {5657// Post the CFLH58JvmtiCachedClassFileData* cached_class_file = NULL;59if (cfs == NULL) {60cfs = FileMapInfo::open_stream_for_jvmti(ik, class_loader, CHECK_NULL);61}62unsigned char* ptr = (unsigned char*)cfs->buffer();63unsigned char* end_ptr = ptr + cfs->length();64unsigned char* old_ptr = ptr;65JvmtiExport::post_class_file_load_hook(class_name,66class_loader,67protection_domain,68&ptr,69&end_ptr,70&cached_class_file);71if (old_ptr != ptr) {72// JVMTI agent has modified class file data.73// Set new class file stream using JVMTI agent modified class file data.74ClassLoaderData* loader_data =75ClassLoaderData::class_loader_data(class_loader());76int path_index = ik->shared_classpath_index();77ClassFileStream* stream = new ClassFileStream(ptr,78end_ptr - ptr,79cfs->source(),80ClassFileStream::verify);81ClassLoadInfo cl_info(protection_domain);82ClassFileParser parser(stream,83class_name,84loader_data,85&cl_info,86ClassFileParser::BROADCAST, // publicity level87CHECK_NULL);88const ClassInstanceInfo* cl_inst_info = cl_info.class_hidden_info_ptr();89InstanceKlass* new_ik = parser.create_instance_klass(true, // changed_by_loadhook90*cl_inst_info, // dynamic_nest_host and classData91CHECK_NULL);9293if (cached_class_file != NULL) {94new_ik->set_cached_class_file(cached_class_file);95}9697if (class_loader.is_null()) {98new_ik->set_classpath_index(path_index);99}100101return new_ik;102}103}104#endif105106return NULL;107}108109110static ClassFileStream* check_class_file_load_hook(ClassFileStream* stream,111Symbol* name,112ClassLoaderData* loader_data,113Handle protection_domain,114JvmtiCachedClassFileData** cached_class_file,115TRAPS) {116117assert(stream != NULL, "invariant");118119if (JvmtiExport::should_post_class_file_load_hook()) {120const JavaThread* jt = THREAD;121122Handle class_loader(THREAD, loader_data->class_loader());123124// Get the cached class file bytes (if any) from the class that125// is being redefined or retransformed. We use jvmti_thread_state()126// instead of JvmtiThreadState::state_for(jt) so we don't allocate127// a JvmtiThreadState any earlier than necessary. This will help128// avoid the bug described by 7126851.129130JvmtiThreadState* state = jt->jvmti_thread_state();131132if (state != NULL) {133Klass* k = state->get_class_being_redefined();134135if (k != NULL) {136InstanceKlass* class_being_redefined = InstanceKlass::cast(k);137*cached_class_file = class_being_redefined->get_cached_class_file();138}139}140141unsigned char* ptr = const_cast<unsigned char*>(stream->buffer());142unsigned char* end_ptr = ptr + stream->length();143144JvmtiExport::post_class_file_load_hook(name,145class_loader,146protection_domain,147&ptr,148&end_ptr,149cached_class_file);150151if (ptr != stream->buffer()) {152// JVMTI agent has modified class file data.153// Set new class file stream using JVMTI agent modified class file data.154stream = new ClassFileStream(ptr,155end_ptr - ptr,156stream->source(),157stream->need_verify());158}159}160161return stream;162}163164165InstanceKlass* KlassFactory::create_from_stream(ClassFileStream* stream,166Symbol* name,167ClassLoaderData* loader_data,168const ClassLoadInfo& cl_info,169TRAPS) {170assert(stream != NULL, "invariant");171assert(loader_data != NULL, "invariant");172173ResourceMark rm(THREAD);174HandleMark hm(THREAD);175176JvmtiCachedClassFileData* cached_class_file = NULL;177178ClassFileStream* old_stream = stream;179180// increment counter181THREAD->statistical_info().incr_define_class_count();182183// Skip this processing for VM hidden classes184if (!cl_info.is_hidden()) {185stream = check_class_file_load_hook(stream,186name,187loader_data,188cl_info.protection_domain(),189&cached_class_file,190CHECK_NULL);191}192193ClassFileParser parser(stream,194name,195loader_data,196&cl_info,197ClassFileParser::BROADCAST, // publicity level198CHECK_NULL);199200const ClassInstanceInfo* cl_inst_info = cl_info.class_hidden_info_ptr();201InstanceKlass* result = parser.create_instance_klass(old_stream != stream, *cl_inst_info, CHECK_NULL);202assert(result != NULL, "result cannot be null with no pending exception");203204if (cached_class_file != NULL) {205// JVMTI: we have an InstanceKlass now, tell it about the cached bytes206result->set_cached_class_file(cached_class_file);207}208209JFR_ONLY(ON_KLASS_CREATION(result, parser, THREAD);)210211#if INCLUDE_CDS212if (Arguments::is_dumping_archive()) {213ClassLoader::record_result(THREAD, result, stream);214}215#endif // INCLUDE_CDS216217return result;218}219220221