1 /* 2 * Copyright (c) 2022, 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/cdsConfig.hpp" 28 #include "cds/classPrelinker.hpp" 29 #include "classfile/systemDictionary.hpp" 30 #include "classfile/vmClasses.hpp" 31 #include "memory/resourceArea.hpp" 32 #include "oops/constantPool.inline.hpp" 33 #include "oops/instanceKlass.hpp" 34 #include "oops/klass.inline.hpp" 35 #include "runtime/handles.inline.hpp" 36 37 ClassPrelinker::ClassesTable* ClassPrelinker::_processed_classes = nullptr; 38 ClassPrelinker::ClassesTable* ClassPrelinker::_vm_classes = nullptr; 39 40 bool ClassPrelinker::is_vm_class(InstanceKlass* ik) { 41 return (_vm_classes->get(ik) != nullptr); 42 } 43 44 void ClassPrelinker::add_one_vm_class(InstanceKlass* ik) { 45 bool created; 46 _vm_classes->put_if_absent(ik, &created); 47 if (created) { 48 InstanceKlass* super = ik->java_super(); 49 if (super != nullptr) { 50 add_one_vm_class(super); 51 } 52 Array<InstanceKlass*>* ifs = ik->local_interfaces(); 53 for (int i = 0; i < ifs->length(); i++) { 54 add_one_vm_class(ifs->at(i)); 55 } 56 } 57 } 58 59 void ClassPrelinker::initialize() { 60 assert(_vm_classes == nullptr, "must be"); 61 _vm_classes = new (mtClass)ClassesTable(); 62 _processed_classes = new (mtClass)ClassesTable(); 63 for (auto id : EnumRange<vmClassID>{}) { 64 add_one_vm_class(vmClasses::klass_at(id)); 65 } 66 } 67 68 void ClassPrelinker::dispose() { 69 assert(_vm_classes != nullptr, "must be"); 70 delete _vm_classes; 71 delete _processed_classes; 72 _vm_classes = nullptr; 73 _processed_classes = nullptr; 74 } 75 76 bool ClassPrelinker::can_archive_resolved_klass(ConstantPool* cp, int cp_index) { 77 assert(!is_in_archivebuilder_buffer(cp), "sanity"); 78 assert(cp->tag_at(cp_index).is_klass(), "must be resolved"); 79 80 Klass* resolved_klass = cp->resolved_klass_at(cp_index); 81 assert(resolved_klass != nullptr, "must be"); 82 83 return can_archive_resolved_klass(cp->pool_holder(), resolved_klass); 84 } 85 86 bool ClassPrelinker::can_archive_resolved_klass(InstanceKlass* cp_holder, Klass* resolved_klass) { 87 assert(!is_in_archivebuilder_buffer(cp_holder), "sanity"); 88 assert(!is_in_archivebuilder_buffer(resolved_klass), "sanity"); 89 90 if (resolved_klass->is_instance_klass()) { 91 InstanceKlass* ik = InstanceKlass::cast(resolved_klass); 92 if (is_vm_class(ik)) { // These are safe to resolve. See is_vm_class declaration. 93 assert(ik->is_shared_boot_class(), "vmClasses must be loaded by boot loader"); 94 if (cp_holder->is_shared_boot_class()) { 95 // For now, do this for boot loader only. Other loaders 96 // must go through ConstantPool::klass_at_impl at runtime 97 // to put this class in their directory. 98 99 // TODO: we can support the platform and app loaders as well, if we 100 // preload the vmClasses into these two loaders during VM bootstrap. 101 return true; 102 } 103 } 104 105 if (cp_holder->is_subtype_of(ik)) { 106 // All super types of ik will be resolved in ik->class_loader() before 107 // ik is defined in this loader, so it's safe to archive the resolved klass reference. 108 return true; 109 } 110 111 // TODO -- allow objArray classes, too 112 } 113 114 return false; 115 } 116 117 void ClassPrelinker::dumptime_resolve_constants(InstanceKlass* ik, TRAPS) { 118 constantPoolHandle cp(THREAD, ik->constants()); 119 if (cp->cache() == nullptr || cp->reference_map() == nullptr) { 120 // The cache may be null if the pool_holder klass fails verification 121 // at dump time due to missing dependencies. 122 return; 123 } 124 125 bool first_time; 126 _processed_classes->put_if_absent(ik, &first_time); 127 if (!first_time) { 128 // We have already resolved the constants in class, so no need to do it again. 129 return; 130 } 131 132 for (int cp_index = 1; cp_index < cp->length(); cp_index++) { // Index 0 is unused 133 switch (cp->tag_at(cp_index).value()) { 134 case JVM_CONSTANT_UnresolvedClass: 135 maybe_resolve_class(cp, cp_index, CHECK); 136 break; 137 138 case JVM_CONSTANT_String: 139 resolve_string(cp, cp_index, CHECK); // may throw OOM when interning strings. 140 break; 141 } 142 } 143 } 144 145 Klass* ClassPrelinker::find_loaded_class(JavaThread* THREAD, oop class_loader, Symbol* name) { 146 HandleMark hm(THREAD); 147 Handle h_loader(THREAD, class_loader); 148 Klass* k = SystemDictionary::find_instance_or_array_klass(THREAD, name, 149 h_loader, 150 Handle()); 151 if (k != nullptr) { 152 return k; 153 } 154 if (class_loader == SystemDictionary::java_system_loader()) { 155 return find_loaded_class(THREAD, SystemDictionary::java_platform_loader(), name); 156 } else if (class_loader == SystemDictionary::java_platform_loader()) { 157 return find_loaded_class(THREAD, nullptr, name); 158 } 159 160 return nullptr; 161 } 162 163 Klass* ClassPrelinker::maybe_resolve_class(constantPoolHandle cp, int cp_index, TRAPS) { 164 assert(!is_in_archivebuilder_buffer(cp()), "sanity"); 165 InstanceKlass* cp_holder = cp->pool_holder(); 166 if (!cp_holder->is_shared_boot_class() && 167 !cp_holder->is_shared_platform_class() && 168 !cp_holder->is_shared_app_class()) { 169 // Don't trust custom loaders, as they may not be well-behaved 170 // when resolving classes. 171 return nullptr; 172 } 173 174 Symbol* name = cp->klass_name_at(cp_index); 175 Klass* resolved_klass = find_loaded_class(THREAD, cp_holder->class_loader(), name); 176 if (resolved_klass != nullptr && can_archive_resolved_klass(cp_holder, resolved_klass)) { 177 Klass* k = cp->klass_at(cp_index, CHECK_NULL); // Should fail only with OOM 178 assert(k == resolved_klass, "must be"); 179 } 180 181 return resolved_klass; 182 } 183 184 #if INCLUDE_CDS_JAVA_HEAP 185 void ClassPrelinker::resolve_string(constantPoolHandle cp, int cp_index, TRAPS) { 186 if (CDSConfig::is_dumping_heap()) { 187 int cache_index = cp->cp_to_object_index(cp_index); 188 ConstantPool::string_at_impl(cp, cp_index, cache_index, CHECK); 189 } 190 } 191 #endif 192 193 #ifdef ASSERT 194 bool ClassPrelinker::is_in_archivebuilder_buffer(address p) { 195 if (!Thread::current()->is_VM_thread() || ArchiveBuilder::current() == nullptr) { 196 return false; 197 } else { 198 return ArchiveBuilder::current()->is_in_buffer_space(p); 199 } 200 } 201 #endif