1 /*
2 * Copyright (c) 2020, 2023, 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 "precompiled.hpp"
26 #include "cds/archiveBuilder.hpp"
27 #include "cds/lambdaFormInvokers.hpp"
28 #include "cds/metaspaceShared.hpp"
29 #include "cds/regeneratedClasses.hpp"
30 #include "classfile/classLoadInfo.hpp"
31 #include "classfile/classFileStream.hpp"
32 #include "classfile/javaClasses.inline.hpp"
33 #include "classfile/klassFactory.hpp"
34 #include "classfile/symbolTable.hpp"
35 #include "classfile/systemDictionary.hpp"
36 #include "classfile/systemDictionaryShared.hpp"
37 #include "classfile/vmClasses.hpp"
38 #include "classfile/vmSymbols.hpp"
39 #include "logging/log.hpp"
40 #include "memory/oopFactory.hpp"
41 #include "memory/resourceArea.hpp"
42 #include "oops/instanceKlass.hpp"
43 #include "oops/klass.inline.hpp"
44 #include "oops/objArrayKlass.hpp"
45 #include "oops/objArrayOop.hpp"
46 #include "oops/oop.inline.hpp"
73 MutexLocker ml(Thread::current(), LambdaFormInvokers_lock);
74 if (_lambdaform_lines == nullptr) {
75 _lambdaform_lines = new GrowableArrayCHeap<char*, mtClassShared>(150);
76 }
77 _lambdaform_lines->append(line);
78 }
79
80
81 // convenient output
82 class PrintLambdaFormMessage {
83 public:
84 PrintLambdaFormMessage() {
85 log_info(cds)("Regenerate MethodHandle Holder classes...");
86 }
87 ~PrintLambdaFormMessage() {
88 log_info(cds)("Regenerate MethodHandle Holder classes...done");
89 }
90 };
91
92 void LambdaFormInvokers::regenerate_holder_classes(TRAPS) {
93 PrintLambdaFormMessage plm;
94 if (_lambdaform_lines == nullptr || _lambdaform_lines->length() == 0) {
95 log_info(cds)("Nothing to regenerate for holder classes");
96 return;
97 }
98
99 ResourceMark rm(THREAD);
100
101 Symbol* cds_name = vmSymbols::jdk_internal_misc_CDS();
102 Klass* cds_klass = SystemDictionary::resolve_or_null(cds_name, THREAD);
103 guarantee(cds_klass != nullptr, "jdk/internal/misc/CDS must exist!");
104
105 HandleMark hm(THREAD);
106 int len = _lambdaform_lines->length();
107 objArrayHandle list_lines;
108 {
109 MutexLocker ml(Thread::current(), LambdaFormInvokers_lock);
110 list_lines = oopFactory::new_objArray_handle(vmClasses::String_klass(), len, CHECK);
111 for (int i = 0; i < len; i++) {
112 Handle h_line = java_lang_String::create_from_str(_lambdaform_lines->at(i), CHECK);
150 if (strstr(class_name, "java/lang/invoke/BoundMethodHandle$Species_") != nullptr) {
151 // The species classes are already loaded into the system dictionary
152 // during the execution of CDS.generateLambdaFormHolderClasses(). No
153 // need to regenerate.
154 TempNewSymbol class_name_sym = SymbolTable::new_symbol(class_name);
155 Klass* klass = SystemDictionary::resolve_or_null(class_name_sym, THREAD);
156 assert(klass != nullptr, "must already be loaded");
157 if (!klass->is_shared() && klass->shared_classpath_index() < 0) {
158 // Fake it, so that it will be included into the archive.
159 klass->set_shared_classpath_index(0);
160 // Set the "generated" bit, so it won't interfere with JVMTI.
161 // See SystemDictionaryShared::find_builtin_class().
162 klass->set_is_generated_shared_class();
163 }
164 } else {
165 int len = h_bytes->length();
166 // make a copy of class bytes so GC will not affect us.
167 char *buf = NEW_RESOURCE_ARRAY(char, len);
168 memcpy(buf, (char*)h_bytes->byte_at_addr(0), len);
169 ClassFileStream st((u1*)buf, len, nullptr, ClassFileStream::verify);
170 regenerate_class(class_name, st, CHECK);
171 }
172 }
173 }
174
175 void LambdaFormInvokers::regenerate_class(char* class_name, ClassFileStream& st, TRAPS) {
176 TempNewSymbol class_name_sym = SymbolTable::new_symbol(class_name);
177 Klass* klass = SystemDictionary::resolve_or_null(class_name_sym, THREAD);
178 assert(klass != nullptr, "must exist");
179 assert(klass->is_instance_klass(), "Should be");
180
181 ClassLoaderData* cld = ClassLoaderData::the_null_class_loader_data();
182 Handle protection_domain;
183 ClassLoadInfo cl_info(protection_domain);
184
185 InstanceKlass* result = KlassFactory::create_from_stream(&st,
186 class_name_sym,
187 cld,
188 cl_info,
189 CHECK);
190
191 assert(result->java_mirror() != nullptr, "must be");
192 RegeneratedClasses::add_class(InstanceKlass::cast(klass), result);
193
194 result->add_to_hierarchy(THREAD);
195
196 // new class not linked yet.
197 MetaspaceShared::try_link_class(THREAD, result);
198 assert(!HAS_PENDING_EXCEPTION, "Invariant");
199
200 result->set_is_generated_shared_class();
201 if (!klass->is_shared()) {
202 SystemDictionaryShared::set_excluded(InstanceKlass::cast(klass)); // exclude the existing class from dump
203 }
204 log_info(cds, lambda)("Regenerated class %s, old: " INTPTR_FORMAT " new: " INTPTR_FORMAT,
205 class_name, p2i(klass), p2i(result));
206 }
207
208 void LambdaFormInvokers::dump_static_archive_invokers() {
209 if (_lambdaform_lines != nullptr && _lambdaform_lines->length() > 0) {
210 int count = 0;
211 int len = _lambdaform_lines->length();
212 for (int i = 0; i < len; i++) {
213 char* str = _lambdaform_lines->at(i);
214 if (should_be_archived(str)) {
215 count++;
216 }
217 }
218 if (count > 0) {
219 _static_archive_invokers = ArchiveBuilder::new_ro_array<Array<char>*>(count);
220 int index = 0;
221 for (int i = 0; i < len; i++) {
222 char* str = _lambdaform_lines->at(i);
223 if (should_be_archived(str)) {
224 size_t str_len = strlen(str) + 1; // including terminating zero
225 Array<char>* line = ArchiveBuilder::new_ro_array<char>((int)str_len);
226 strncpy(line->adr_at(0), str, str_len);
227
228 _static_archive_invokers->at_put(index, line);
|
1 /*
2 * Copyright (c) 2020, 2024, 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 "precompiled.hpp"
26 #include "cds/archiveBuilder.hpp"
27 #include "cds/cdsConfig.hpp"
28 #include "cds/lambdaFormInvokers.hpp"
29 #include "cds/metaspaceShared.hpp"
30 #include "cds/regeneratedClasses.hpp"
31 #include "classfile/classLoadInfo.hpp"
32 #include "classfile/classFileStream.hpp"
33 #include "classfile/javaClasses.inline.hpp"
34 #include "classfile/klassFactory.hpp"
35 #include "classfile/symbolTable.hpp"
36 #include "classfile/systemDictionary.hpp"
37 #include "classfile/systemDictionaryShared.hpp"
38 #include "classfile/vmClasses.hpp"
39 #include "classfile/vmSymbols.hpp"
40 #include "logging/log.hpp"
41 #include "memory/oopFactory.hpp"
42 #include "memory/resourceArea.hpp"
43 #include "oops/instanceKlass.hpp"
44 #include "oops/klass.inline.hpp"
45 #include "oops/objArrayKlass.hpp"
46 #include "oops/objArrayOop.hpp"
47 #include "oops/oop.inline.hpp"
74 MutexLocker ml(Thread::current(), LambdaFormInvokers_lock);
75 if (_lambdaform_lines == nullptr) {
76 _lambdaform_lines = new GrowableArrayCHeap<char*, mtClassShared>(150);
77 }
78 _lambdaform_lines->append(line);
79 }
80
81
82 // convenient output
83 class PrintLambdaFormMessage {
84 public:
85 PrintLambdaFormMessage() {
86 log_info(cds)("Regenerate MethodHandle Holder classes...");
87 }
88 ~PrintLambdaFormMessage() {
89 log_info(cds)("Regenerate MethodHandle Holder classes...done");
90 }
91 };
92
93 void LambdaFormInvokers::regenerate_holder_classes(TRAPS) {
94 if (!CDSConfig::is_dumping_regenerated_lambdaform_invokers()) {
95 return;
96 }
97 PrintLambdaFormMessage plm;
98 if (_lambdaform_lines == nullptr || _lambdaform_lines->length() == 0) {
99 log_info(cds)("Nothing to regenerate for holder classes");
100 return;
101 }
102
103 ResourceMark rm(THREAD);
104
105 Symbol* cds_name = vmSymbols::jdk_internal_misc_CDS();
106 Klass* cds_klass = SystemDictionary::resolve_or_null(cds_name, THREAD);
107 guarantee(cds_klass != nullptr, "jdk/internal/misc/CDS must exist!");
108
109 HandleMark hm(THREAD);
110 int len = _lambdaform_lines->length();
111 objArrayHandle list_lines;
112 {
113 MutexLocker ml(Thread::current(), LambdaFormInvokers_lock);
114 list_lines = oopFactory::new_objArray_handle(vmClasses::String_klass(), len, CHECK);
115 for (int i = 0; i < len; i++) {
116 Handle h_line = java_lang_String::create_from_str(_lambdaform_lines->at(i), CHECK);
154 if (strstr(class_name, "java/lang/invoke/BoundMethodHandle$Species_") != nullptr) {
155 // The species classes are already loaded into the system dictionary
156 // during the execution of CDS.generateLambdaFormHolderClasses(). No
157 // need to regenerate.
158 TempNewSymbol class_name_sym = SymbolTable::new_symbol(class_name);
159 Klass* klass = SystemDictionary::resolve_or_null(class_name_sym, THREAD);
160 assert(klass != nullptr, "must already be loaded");
161 if (!klass->is_shared() && klass->shared_classpath_index() < 0) {
162 // Fake it, so that it will be included into the archive.
163 klass->set_shared_classpath_index(0);
164 // Set the "generated" bit, so it won't interfere with JVMTI.
165 // See SystemDictionaryShared::find_builtin_class().
166 klass->set_is_generated_shared_class();
167 }
168 } else {
169 int len = h_bytes->length();
170 // make a copy of class bytes so GC will not affect us.
171 char *buf = NEW_RESOURCE_ARRAY(char, len);
172 memcpy(buf, (char*)h_bytes->byte_at_addr(0), len);
173 ClassFileStream st((u1*)buf, len, nullptr, ClassFileStream::verify);
174 if (!ArchiveInvokeDynamic /* disabled for ArchiveInvokeDynamic because of JDK-8310831 */) {
175 regenerate_class(class_name, st, CHECK);
176 }
177 }
178 }
179 }
180
181 void LambdaFormInvokers::regenerate_class(char* class_name, ClassFileStream& st, TRAPS) {
182 TempNewSymbol class_name_sym = SymbolTable::new_symbol(class_name);
183 Klass* klass = SystemDictionary::resolve_or_null(class_name_sym, THREAD);
184 assert(klass != nullptr, "must exist");
185 assert(klass->is_instance_klass(), "Should be");
186
187 ClassLoaderData* cld = ClassLoaderData::the_null_class_loader_data();
188 Handle protection_domain;
189 ClassLoadInfo cl_info(protection_domain);
190
191 InstanceKlass* result = KlassFactory::create_from_stream(&st,
192 class_name_sym,
193 cld,
194 cl_info,
195 CHECK);
196
197 assert(result->java_mirror() != nullptr, "must be");
198 RegeneratedClasses::add_class(InstanceKlass::cast(klass), result);
199
200 result->add_to_hierarchy(THREAD);
201
202 // new class not linked yet.
203 MetaspaceShared::try_link_class(THREAD, result);
204 assert(!HAS_PENDING_EXCEPTION, "Invariant");
205
206 result->set_is_generated_shared_class();
207 if (!klass->is_shared()) {
208 SystemDictionaryShared::set_excluded(InstanceKlass::cast(klass)); // exclude the existing class from dump
209 }
210 log_info(cds, lambda)("Regenerated class %s, old: " INTPTR_FORMAT " new: " INTPTR_FORMAT,
211 class_name, p2i(klass), p2i(result));
212 }
213
214 void LambdaFormInvokers::dump_static_archive_invokers() {
215 if (CDSConfig::is_dumping_preimage_static_archive() ||
216 CDSConfig::is_dumping_final_static_archive()) {
217 // This function writes the "names" of the invokers.
218 // This is not supported in new CDS workflow for now.
219 return;
220 }
221
222 if (_lambdaform_lines != nullptr && _lambdaform_lines->length() > 0) {
223 int count = 0;
224 int len = _lambdaform_lines->length();
225 for (int i = 0; i < len; i++) {
226 char* str = _lambdaform_lines->at(i);
227 if (should_be_archived(str)) {
228 count++;
229 }
230 }
231 if (count > 0) {
232 _static_archive_invokers = ArchiveBuilder::new_ro_array<Array<char>*>(count);
233 int index = 0;
234 for (int i = 0; i < len; i++) {
235 char* str = _lambdaform_lines->at(i);
236 if (should_be_archived(str)) {
237 size_t str_len = strlen(str) + 1; // including terminating zero
238 Array<char>* line = ArchiveBuilder::new_ro_array<char>((int)str_len);
239 strncpy(line->adr_at(0), str, str_len);
240
241 _static_archive_invokers->at_put(index, line);
|