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);
113 list_lines->obj_at_put(i, h_line());
114 }
115 } // Before calling into java, release vm lock.
116 //
117 // Object[] CDS.generateLambdaFormHolderClasses(String[] lines)
118 // the returned Object[] layout:
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 if (CDSConfig::is_dumping_static_archive() && CDSConfig::is_dumping_invokedynamic()) {
104 // Work around JDK-8310831, as some methods in lambda form holder classes may not get generated.
105 log_info(cds)("Archived MethodHandles may refer to lambda form holder classes. Cannot regenerate.");
106 return;
107 }
108
109 if (CDSConfig::is_dumping_dynamic_archive() && CDSConfig::is_dumping_aot_linked_classes() &&
110 CDSConfig::is_using_aot_linked_classes()) {
111 // The base archive may have some pre-resolved CP entries that point to the lambda form holder
112 // classes in the base archive. If we generate new versions of these classes, those CP entries
113 // will be pointing to invalid classes.
114 log_info(cds)("Base archive already have aot-linked lambda form holder classes. Cannot regenerate.");
115 return;
116 }
117
118 ResourceMark rm(THREAD);
119
120 Symbol* cds_name = vmSymbols::jdk_internal_misc_CDS();
121 Klass* cds_klass = SystemDictionary::resolve_or_null(cds_name, THREAD);
122 guarantee(cds_klass != nullptr, "jdk/internal/misc/CDS must exist!");
123
124 HandleMark hm(THREAD);
125 int len = _lambdaform_lines->length();
126 objArrayHandle list_lines;
127 {
128 MutexLocker ml(Thread::current(), LambdaFormInvokers_lock);
129 list_lines = oopFactory::new_objArray_handle(vmClasses::String_klass(), len, CHECK);
130 for (int i = 0; i < len; i++) {
131 Handle h_line = java_lang_String::create_from_str(_lambdaform_lines->at(i), CHECK);
132 list_lines->obj_at_put(i, h_line());
133 }
134 } // Before calling into java, release vm lock.
135 //
136 // Object[] CDS.generateLambdaFormHolderClasses(String[] lines)
137 // the returned Object[] layout:
169 if (strstr(class_name, "java/lang/invoke/BoundMethodHandle$Species_") != nullptr) {
170 // The species classes are already loaded into the system dictionary
171 // during the execution of CDS.generateLambdaFormHolderClasses(). No
172 // need to regenerate.
173 TempNewSymbol class_name_sym = SymbolTable::new_symbol(class_name);
174 Klass* klass = SystemDictionary::resolve_or_null(class_name_sym, THREAD);
175 assert(klass != nullptr, "must already be loaded");
176 if (!klass->is_shared() && klass->shared_classpath_index() < 0) {
177 // Fake it, so that it will be included into the archive.
178 klass->set_shared_classpath_index(0);
179 // Set the "generated" bit, so it won't interfere with JVMTI.
180 // See SystemDictionaryShared::find_builtin_class().
181 klass->set_is_generated_shared_class();
182 }
183 } else {
184 int len = h_bytes->length();
185 // make a copy of class bytes so GC will not affect us.
186 char *buf = NEW_RESOURCE_ARRAY(char, len);
187 memcpy(buf, (char*)h_bytes->byte_at_addr(0), len);
188 ClassFileStream st((u1*)buf, len, nullptr, ClassFileStream::verify);
189 if (!CDSConfig::is_dumping_invokedynamic() /* work around JDK-8310831 */) {
190 regenerate_class(class_name, st, CHECK);
191 }
192 }
193 }
194 }
195
196 void LambdaFormInvokers::regenerate_class(char* class_name, ClassFileStream& st, TRAPS) {
197 TempNewSymbol class_name_sym = SymbolTable::new_symbol(class_name);
198 Klass* klass = SystemDictionary::resolve_or_null(class_name_sym, THREAD);
199 assert(klass != nullptr, "must exist");
200 assert(klass->is_instance_klass(), "Should be");
201
202 ClassLoaderData* cld = ClassLoaderData::the_null_class_loader_data();
203 Handle protection_domain;
204 ClassLoadInfo cl_info(protection_domain);
205
206 InstanceKlass* result = KlassFactory::create_from_stream(&st,
207 class_name_sym,
208 cld,
209 cl_info,
210 CHECK);
211
212 assert(result->java_mirror() != nullptr, "must be");
213 RegeneratedClasses::add_class(InstanceKlass::cast(klass), result);
214
215 result->add_to_hierarchy(THREAD);
216
217 // new class not linked yet.
218 MetaspaceShared::try_link_class(THREAD, result);
219 assert(!HAS_PENDING_EXCEPTION, "Invariant");
220
221 result->set_is_generated_shared_class();
222 if (!klass->is_shared()) {
223 SystemDictionaryShared::set_excluded(InstanceKlass::cast(klass)); // exclude the existing class from dump
224 }
225 log_info(cds, lambda)("Regenerated class %s, old: " INTPTR_FORMAT " new: " INTPTR_FORMAT,
226 class_name, p2i(klass), p2i(result));
227 }
228
229 void LambdaFormInvokers::dump_static_archive_invokers() {
230 if (CDSConfig::is_dumping_preimage_static_archive() ||
231 CDSConfig::is_dumping_final_static_archive()) {
232 // This function writes the "names" of the invokers.
233 // This is not supported in new CDS workflow for now.
234 return;
235 }
236
237 if (_lambdaform_lines != nullptr && _lambdaform_lines->length() > 0) {
238 int count = 0;
239 int len = _lambdaform_lines->length();
240 for (int i = 0; i < len; i++) {
241 char* str = _lambdaform_lines->at(i);
242 if (should_be_archived(str)) {
243 count++;
244 }
245 }
246 if (count > 0) {
247 _static_archive_invokers = ArchiveBuilder::new_ro_array<Array<char>*>(count);
248 int index = 0;
249 for (int i = 0; i < len; i++) {
250 char* str = _lambdaform_lines->at(i);
251 if (should_be_archived(str)) {
252 size_t str_len = strlen(str) + 1; // including terminating zero
253 Array<char>* line = ArchiveBuilder::new_ro_array<char>((int)str_len);
254 strncpy(line->adr_at(0), str, str_len);
255
256 _static_archive_invokers->at_put(index, line);
|