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