1 /*
  2 * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
  3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4 *
  5 * This code is free software; you can redistribute it and/or modify it
  6 * under the terms of the GNU General Public License version 2 only, as
  7 * published by the Free Software Foundation.
  8 *
  9 * This code is distributed in the hope that it will be useful, but WITHOUT
 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12 * version 2 for more details (a copy is included in the LICENSE file that
 13 * accompanied this code).
 14 *
 15 * You should have received a copy of the GNU General Public License version
 16 * 2 along with this work; if not, write to the Free Software Foundation,
 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18 *
 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20 * or visit www.oracle.com if you need additional information or have any
 21 * questions.
 22 *
 23 */
 24 
 25 #include "cds/cds_globals.hpp"
 26 #include "cds/cdsConfig.hpp"
 27 #include "cds/filemap.hpp"
 28 #include "classfile/classFileParser.hpp"
 29 #include "classfile/classFileStream.hpp"
 30 #include "classfile/classLoader.hpp"
 31 #include "classfile/classLoaderData.inline.hpp"
 32 #include "classfile/classLoadInfo.hpp"
 33 #include "classfile/klassFactory.hpp"
 34 #include "classfile/systemDictionaryShared.hpp"
 35 #include "memory/resourceArea.hpp"
 36 #include "prims/jvmtiEnvBase.hpp"
 37 #include "prims/jvmtiRedefineClasses.hpp"
 38 #include "runtime/handles.inline.hpp"
 39 #include "utilities/macros.hpp"
 40 #if INCLUDE_JFR
 41 #include "jfr/jfr.hpp"
 42 #endif
 43 
 44 
 45 // called during initial loading of a shared class
 46 InstanceKlass* KlassFactory::check_shared_class_file_load_hook(
 47                                           InstanceKlass* ik,
 48                                           Symbol* class_name,
 49                                           Handle class_loader,
 50                                           Handle protection_domain,
 51                                           const ClassFileStream *cfs,
 52                                           TRAPS) {
 53 #if INCLUDE_CDS && INCLUDE_JVMTI
 54   assert(ik != nullptr, "sanity");
 55   assert(ik->in_aot_cache(), "expecting a shared class");
 56   if (JvmtiExport::should_post_class_file_load_hook()) {
 57     ResourceMark rm(THREAD);
 58     // Post the CFLH
 59     JvmtiCachedClassFileData* cached_class_file = nullptr;
 60     if (cfs == nullptr) {
 61       cfs = FileMapInfo::open_stream_for_jvmti(ik, class_loader, CHECK_NULL);
 62     }
 63     unsigned char* ptr = (unsigned char*)cfs->buffer();
 64     unsigned char* end_ptr = ptr + cfs->length();
 65     unsigned char* old_ptr = ptr;
 66     JvmtiExport::post_class_file_load_hook(class_name,
 67                                            class_loader,
 68                                            protection_domain,
 69                                            &ptr,
 70                                            &end_ptr,
 71                                            &cached_class_file);
 72     if (old_ptr != ptr) {
 73       // JVMTI agent has modified class file data.
 74       // Set new class file stream using JVMTI agent modified class file data.
 75       ClassLoaderData* loader_data =
 76         ClassLoaderData::class_loader_data(class_loader());
 77       s2 path_index = ik->shared_classpath_index();
 78       ClassFileStream* stream = new ClassFileStream(ptr,
 79                                                     pointer_delta_as_int(end_ptr, ptr),
 80                                                     cfs->source(),
 81                                                     /* from_boot_loader_modules_image */ false,
 82                                                     /* from_class_file_load_hook */ true);
 83       ClassLoadInfo cl_info(protection_domain);
 84       ClassFileParser parser(stream,
 85                              class_name,
 86                              loader_data,
 87                              &cl_info,
 88                              ClassFileParser::BROADCAST, // publicity level
 89                              CHECK_NULL);
 90       const ClassInstanceInfo* cl_inst_info = cl_info.class_hidden_info_ptr();
 91       InstanceKlass* new_ik = parser.create_instance_klass(true, // changed_by_loadhook
 92                                                            *cl_inst_info,  // dynamic_nest_host and classData
 93                                                            CHECK_NULL);
 94 
 95       if (cached_class_file != nullptr) {
 96         new_ik->set_cached_class_file(cached_class_file);
 97       }
 98 
 99       if (class_loader.is_null()) {
100         new_ik->set_classpath_index(path_index);
101       }
102 
103 
104       JFR_ONLY(Jfr::on_klass_creation(new_ik, parser, THREAD);)
105 
106       return new_ik;
107     }
108   }
109 #endif
110 
111   return nullptr;
112 }
113 
114 
115 static ClassFileStream* check_class_file_load_hook(ClassFileStream* stream,
116                                                    Symbol* name,
117                                                    ClassLoaderData* loader_data,
118                                                    Handle protection_domain,
119                                                    JvmtiCachedClassFileData** cached_class_file,
120                                                    TRAPS) {
121 
122   assert(stream != nullptr, "invariant");
123 
124   if (JvmtiExport::should_post_class_file_load_hook()) {
125     const JavaThread* jt = THREAD;
126 
127     Handle class_loader(THREAD, loader_data->class_loader());
128 
129     // Get the cached class file bytes (if any) from the class that
130     // is being retransformed. If class file load hook provides
131     // modified class data during class loading or redefinition,
132     // new cached class file buffer should be allocated.
133     // We use jvmti_thread_state()
134     // instead of JvmtiThreadState::state_for(jt) so we don't allocate
135     // a JvmtiThreadState any earlier than necessary. This will help
136     // avoid the bug described by 7126851.
137 
138     JvmtiThreadState* state = jt->jvmti_thread_state();
139 
140     if (state != nullptr) {
141       Klass* k = state->get_class_being_redefined();
142       if (k != nullptr && state->get_class_load_kind() == jvmti_class_load_kind_retransform) {
143         InstanceKlass* class_being_redefined = InstanceKlass::cast(k);
144         *cached_class_file = class_being_redefined->get_cached_class_file();
145       }
146     }
147 
148     unsigned char* ptr = const_cast<unsigned char*>(stream->buffer());
149     unsigned char* end_ptr = ptr + stream->length();
150 
151     JvmtiExport::post_class_file_load_hook(name,
152                                            class_loader,
153                                            protection_domain,
154                                            &ptr,
155                                            &end_ptr,
156                                            cached_class_file);
157 
158     if (ptr != stream->buffer()) {
159       // JVMTI agent has modified class file data.
160       // Set new class file stream using JVMTI agent modified class file data.
161       stream = new ClassFileStream(ptr,
162                                    pointer_delta_as_int(end_ptr, ptr),
163                                    stream->source(),
164                                    /* from_boot_loader_modules_image */ false,
165                                    /* from_class_file_load_hook */ true);
166     }
167   }
168 
169   return stream;
170 }
171 
172 
173 InstanceKlass* KlassFactory::create_from_stream(ClassFileStream* stream,
174                                                 Symbol* name,
175                                                 ClassLoaderData* loader_data,
176                                                 const ClassLoadInfo& cl_info,
177                                                 TRAPS) {
178   assert(stream != nullptr, "invariant");
179   assert(loader_data != nullptr, "invariant");
180 
181   ResourceMark rm(THREAD);
182   HandleMark hm(THREAD);
183 
184   JvmtiCachedClassFileData* cached_class_file = nullptr;
185 
186   ClassFileStream* old_stream = stream;
187 
188   // increment counter
189   THREAD->statistical_info().incr_define_class_count();
190 
191   // Skip this processing for VM hidden classes
192   if (!cl_info.is_hidden()) {
193     stream = check_class_file_load_hook(stream,
194                                         name,
195                                         loader_data,
196                                         cl_info.protection_domain(),
197                                         &cached_class_file,
198                                         CHECK_NULL);
199   }
200 
201   ClassFileParser parser(stream,
202                          name,
203                          loader_data,
204                          &cl_info,
205                          ClassFileParser::BROADCAST, // publicity level
206                          CHECK_NULL);
207 
208   const ClassInstanceInfo* cl_inst_info = cl_info.class_hidden_info_ptr();
209   InstanceKlass* result = parser.create_instance_klass(old_stream != stream, *cl_inst_info, CHECK_NULL);
210   assert(result != nullptr, "result cannot be null with no pending exception");
211   if (CDSConfig::is_dumping_archive() && stream->from_class_file_load_hook()) {
212     SystemDictionaryShared::set_from_class_file_load_hook(result);
213   }
214 
215   if (cached_class_file != nullptr) {
216     // JVMTI: we have an InstanceKlass now, tell it about the cached bytes
217     result->set_cached_class_file(cached_class_file);
218   }
219 
220   JFR_ONLY(Jfr::on_klass_creation(result, parser, THREAD);)
221 
222 #if INCLUDE_CDS
223   if (CDSConfig::is_dumping_archive()) {
224     ClassLoader::record_result(THREAD, result, stream, old_stream != stream);
225   }
226 #endif // INCLUDE_CDS
227 
228   return result;
229 }