1 /*
2 * Copyright (c) 2022, 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 *
79 // [A] In most of the cases, the module bootstrap code will update the static field
80 // to point to part of the archived module graph. E.g.,
81 // - java/lang/System::bootLayer
82 // - jdk/internal/loader/ClassLoaders::BOOT_LOADER
83 // [B] A final static String that's explicitly initialized inside <clinit>, but
84 // its value is deterministic and is always the same string literal.
85 // [C] A non-final static string that is assigned a string literal during class
86 // initialization; this string is never changed during -Xshare:dump.
87 // [D] Simple caches whose value doesn't matter.
88 // [E] Other cases (see comments in-line below).
89
90 CDSHeapVerifier::CDSHeapVerifier() : _archived_objs(0), _problems(0)
91 {
92 # define ADD_EXCL(...) { static const char* e[] = {__VA_ARGS__, nullptr}; add_exclusion(e); }
93
94 // Unfortunately this needs to be manually maintained. If
95 // test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchivedEnumTest.java fails,
96 // you might need to fix the core library code, or fix the ADD_EXCL entries below.
97 //
98 // class field type
99 ADD_EXCL("java/lang/ClassLoader", "scl"); // A
100 ADD_EXCL("java/lang/Module", "ALL_UNNAMED_MODULE", // A
101 "ALL_UNNAMED_MODULE_SET", // A
102 "EVERYONE_MODULE", // A
103 "EVERYONE_SET"); // A
104
105 // This is the same as java/util/ImmutableCollections::EMPTY_SET, which is archived
106 ADD_EXCL("java/lang/reflect/AccessFlag$Location", "EMPTY_SET"); // E
107
108 ADD_EXCL("java/lang/System", "bootLayer"); // A
109
110 // A dummy object used by HashSet. The value doesn't matter and it's never
111 // tested for equality.
112 ADD_EXCL("java/util/HashSet", "PRESENT"); // E
113 ADD_EXCL("jdk/internal/loader/BuiltinClassLoader", "packageToModule"); // A
114 ADD_EXCL("jdk/internal/loader/ClassLoaders", "BOOT_LOADER", // A
115 "APP_LOADER", // A
116 "PLATFORM_LOADER"); // A
117 ADD_EXCL("jdk/internal/module/Builder", "cachedVersion"); // D
118 ADD_EXCL("jdk/internal/module/ModuleLoaderMap$Mapper", "APP_CLASSLOADER", // A
119 "APP_LOADER_INDEX", // A
120 "PLATFORM_CLASSLOADER", // A
121 "PLATFORM_LOADER_INDEX"); // A
122 ADD_EXCL("jdk/internal/module/ServicesCatalog", "CLV"); // A
123
124 // This just points to an empty Map
125 ADD_EXCL("jdk/internal/reflect/Reflection", "methodFilterMap"); // E
126
127 // Integer for 0 and 1 are in java/lang/Integer$IntegerCache and are archived
128 ADD_EXCL("sun/invoke/util/ValueConversions", "ONE_INT", // E
129 "ZERO_INT"); // E
130
131 if (CDSConfig::is_dumping_invokedynamic()) {
132 ADD_EXCL("java/lang/invoke/InvokerBytecodeGenerator", "MEMBERNAME_FACTORY", // D
133 "CD_Object_array", // E same as <...>ConstantUtils.CD_Object_array::CD_Object
134 "INVOKER_SUPER_DESC"); // E same as java.lang.constant.ConstantDescs::CD_Object
135 }
136
137 # undef ADD_EXCL
138
139 ClassLoaderDataGraph::classes_do(this);
140 }
141
142 CDSHeapVerifier::~CDSHeapVerifier() {
143 if (_problems > 0) {
144 log_error(cds, heap)("Scanned %d objects. Found %d case(s) where "
145 "an object points to a static field that "
146 "may hold a different value at runtime.", _archived_objs, _problems);
147 MetaspaceShared::unrecoverable_writing_error();
148 }
149 }
150
151 class CDSHeapVerifier::CheckStaticFields : public FieldClosure {
152 CDSHeapVerifier* _verifier;
153 InstanceKlass* _ik; // The class whose static fields are being checked.
154 const char** _exclusions;
155 public:
156 CheckStaticFields(CDSHeapVerifier* verifier, InstanceKlass* ik)
157 : _verifier(verifier), _ik(ik) {
158 _exclusions = _verifier->find_exclusion(_ik);
159 }
160
161 void do_field(fieldDescriptor* fd) {
162 if (fd->field_type() != T_OBJECT) {
163 return;
164 }
165
166 if (fd->signature()->equals("Ljdk/internal/access/JavaLangAccess;")) {
167 // A few classes have static fields that point to SharedSecrets.getJavaLangAccess().
|
1 /*
2 * Copyright (c) 2022, 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 *
79 // [A] In most of the cases, the module bootstrap code will update the static field
80 // to point to part of the archived module graph. E.g.,
81 // - java/lang/System::bootLayer
82 // - jdk/internal/loader/ClassLoaders::BOOT_LOADER
83 // [B] A final static String that's explicitly initialized inside <clinit>, but
84 // its value is deterministic and is always the same string literal.
85 // [C] A non-final static string that is assigned a string literal during class
86 // initialization; this string is never changed during -Xshare:dump.
87 // [D] Simple caches whose value doesn't matter.
88 // [E] Other cases (see comments in-line below).
89
90 CDSHeapVerifier::CDSHeapVerifier() : _archived_objs(0), _problems(0)
91 {
92 # define ADD_EXCL(...) { static const char* e[] = {__VA_ARGS__, nullptr}; add_exclusion(e); }
93
94 // Unfortunately this needs to be manually maintained. If
95 // test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchivedEnumTest.java fails,
96 // you might need to fix the core library code, or fix the ADD_EXCL entries below.
97 //
98 // class field type
99 ADD_EXCL("java/lang/ClassLoader$Holder", "scl"); // A
100 ADD_EXCL("java/lang/Module", "ALL_UNNAMED_MODULE", // A
101 "ALL_UNNAMED_MODULE_SET", // A
102 "EVERYONE_MODULE", // A
103 "EVERYONE_SET"); // A
104
105 // This is the same as java/util/ImmutableCollections::EMPTY_SET, which is archived
106 ADD_EXCL("java/lang/reflect/AccessFlag$Location", "EMPTY_SET"); // E
107
108 ADD_EXCL("java/lang/System", "bootLayer"); // A
109
110 // A dummy object used by HashSet. The value doesn't matter and it's never
111 // tested for equality.
112 ADD_EXCL("java/util/HashSet", "PRESENT"); // E
113 ADD_EXCL("jdk/internal/loader/BuiltinClassLoader", "packageToModule"); // A
114 ADD_EXCL("jdk/internal/loader/ClassLoaders", "BOOT_LOADER", // A
115 "APP_LOADER", // A
116 "PLATFORM_LOADER"); // A
117 ADD_EXCL("jdk/internal/module/Builder", "cachedVersion"); // D
118 ADD_EXCL("jdk/internal/module/ModuleLoaderMap$Mapper", "APP_CLASSLOADER", // A
119 "APP_LOADER_INDEX", // A
120 "PLATFORM_CLASSLOADER", // A
121 "PLATFORM_LOADER_INDEX"); // A
122 ADD_EXCL("jdk/internal/module/ServicesCatalog", "CLV"); // A
123
124 // This just points to an empty Map
125 ADD_EXCL("jdk/internal/reflect/Reflection", "methodFilterMap"); // E
126
127 // Integer for 0 and 1 are in java/lang/Integer$IntegerCache and are archived
128 ADD_EXCL("sun/invoke/util/ValueConversions", "ONE_INT", // E
129 "ZERO_INT"); // E
130
131 if (CDSConfig::is_dumping_invokedynamic()) {
132 ADD_EXCL("java/lang/invoke/InvokerBytecodeGenerator", "MEMBERNAME_FACTORY", // D
133 "CD_Object_array", // E same as <...>ConstantUtils.CD_Object_array::CD_Object
134 "INVOKER_SUPER_DESC"); // E same as java.lang.constant.ConstantDescs::CD_Object
135 }
136
137 // These are used by BuiltinClassLoader::negativeLookupCache, etc but seem to be
138 // OK. TODO - we should completely disable the caching unless ArchiveLoaderLookupCache
139 // is enabled
140 ADD_EXCL("java/lang/Boolean", "TRUE", // E
141 "FALSE"); // E
142
143 # undef ADD_EXCL
144
145 ClassLoaderDataGraph::classes_do(this);
146 }
147
148 CDSHeapVerifier::~CDSHeapVerifier() {
149 if (_problems > 0) {
150 log_error(cds, heap)("Scanned %d objects. Found %d case(s) where "
151 "an object points to a static field that "
152 "may hold a different value at runtime.", _archived_objs, _problems);
153 //MetaspaceShared::unrecoverable_writing_error(); // FIXME -- leyden+JEP483 merge
154 }
155 }
156
157 class CDSHeapVerifier::CheckStaticFields : public FieldClosure {
158 CDSHeapVerifier* _verifier;
159 InstanceKlass* _ik; // The class whose static fields are being checked.
160 const char** _exclusions;
161 public:
162 CheckStaticFields(CDSHeapVerifier* verifier, InstanceKlass* ik)
163 : _verifier(verifier), _ik(ik) {
164 _exclusions = _verifier->find_exclusion(_ik);
165 }
166
167 void do_field(fieldDescriptor* fd) {
168 if (fd->field_type() != T_OBJECT) {
169 return;
170 }
171
172 if (fd->signature()->equals("Ljdk/internal/access/JavaLangAccess;")) {
173 // A few classes have static fields that point to SharedSecrets.getJavaLangAccess().
|