1 /* 2 * Copyright (c) 2003, 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 * 23 */ 24 25 #ifndef SHARE_CDS_AOTCLASSLOCATION_HPP 26 #define SHARE_CDS_AOTCLASSLOCATION_HPP 27 28 #include "memory/allocation.hpp" 29 #include "oops/array.hpp" 30 #include "utilities/exceptions.hpp" 31 #include "utilities/growableArray.hpp" 32 #include "utilities/globalDefinitions.hpp" 33 #include "utilities/macros.hpp" 34 35 class AllClassLocationStreams; 36 class ClassLocationStream; 37 class ClassPathZipEntry; 38 class LogStream; 39 40 // An AOTClassLocation is a location where the application is configured to load Java classes 41 // from. It can be: 42 // - the location of $JAVA_HOME/lib/modules 43 // - an entry in -Xbootclasspath/a 44 // - an entry in -classpath 45 // - a JAR file specified using --module-path. 46 // 47 // AOTClassLocation is similar to java.security.CodeSource, except: 48 // - Only local files/dirs are allowed. Directories must be empty. Network locations are not allowed. 49 // - No code signing information is recorded. 50 // 51 // We avoid using pointers in AOTClassLocation to avoid runtime pointer relocation. Each AOTClassLocation 52 // is a variable-size structure: 53 // [ all fields specified below (sizeof(AOTClassLocation) bytes) ] 54 // [ path (_path_length bytes, including the terminating zero) ] 55 // [ manifest (_manifest_length bytes, including the terminating zero) ] 56 class AOTClassLocation { 57 public: 58 enum class Group : int { 59 MODULES_IMAGE, 60 BOOT_CLASSPATH, 61 APP_CLASSPATH, 62 MODULE_PATH 63 }; 64 private: 65 enum class FileType : int { 66 NORMAL, 67 DIR, 68 NOT_EXIST 69 }; 70 size_t _path_length; // does NOT include terminating zero 71 size_t _manifest_length; // does NOT include terminating zero 72 bool _check_time; 73 bool _from_cpattr; 74 bool _is_multi_release_jar; // is this a JAR file that has multi-release classes? 75 FileType _file_type; 76 Group _group; 77 int _index; // index of this AOTClassLocation inside AOTClassLocationConfig::_class_locations 78 time_t _timestamp; 79 int64_t _filesize; 80 81 static size_t header_size() { return sizeof(AOTClassLocation); } // bytes 82 size_t path_offset() const { return header_size(); } 83 size_t manifest_offset() const { return path_offset() + _path_length + 1; } 84 static char* read_manifest(JavaThread* current, const char* path, size_t& manifest_length); 85 86 public: 87 static AOTClassLocation* allocate(JavaThread* current, const char* path, int index, Group group, 88 bool from_cpattr = false, bool is_jrt = false); 89 90 size_t total_size() const { return manifest_offset() + _manifest_length + 1; } 91 const char* path() const { return ((const char*)this) + path_offset(); } 92 size_t manifest_length() const { return _manifest_length; } 93 const char* manifest() const { return ((const char*)this) + manifest_offset(); } 94 bool must_exist() const { return _file_type != FileType::NOT_EXIST; } 95 bool must_not_exist() const { return _file_type == FileType::NOT_EXIST; } 96 bool is_dir() const { return _file_type == FileType::DIR; } 97 int index() const { return _index; } 98 bool is_modules_image() const { return _group == Group::MODULES_IMAGE; } 99 bool from_boot_classpath() const { return _group == Group::BOOT_CLASSPATH; } 100 bool from_app_classpath() const { return _group == Group::APP_CLASSPATH; } 101 bool from_module_path() const { return _group == Group::MODULE_PATH; } 102 bool is_multi_release_jar() const { return _is_multi_release_jar; } 103 104 // Only boot/app classpaths can contain unnamed module 105 bool has_unnamed_module() const { return from_boot_classpath() || from_app_classpath(); } 106 107 char* get_cpattr() const; 108 AOTClassLocation* write_to_archive() const; 109 110 // Returns true IFF this AOTClassLocation is discovered from the -classpath or -Xbootclasspath/a by parsing the 111 // "Class-Path" attribute of a JAR file. 112 bool from_cpattr() const { return _from_cpattr; } 113 const char* file_type_string() const; 114 bool check(const char* runtime_path, bool has_aot_linked_classes) const; 115 }; 116 117 // AOTClassLocationConfig 118 // 119 // Keep track of the set of AOTClassLocations used when an AOTCache is created. 120 // To load the AOTCache in a production run, the JVM must be using a compatible set of 121 // AOTClassLocations (subjected to AOTClassLocationConfig::validate()). 122 // 123 // In general, validation is performed on the AOTClassLocations to ensure the code locations used 124 // during AOTCache creation are the same as when the AOTCache is used during runtime. 125 // Non-existent entries are recorded during AOTCache creation. Those non-existent entries, 126 // if they are specified at runtime, must not exist. 127 // 128 // Some details on validation: 129 // - the boot classpath can be appended to at runtime if there's no app classpath and no 130 // module path specified when an AOTCache is created; 131 // - the app classpath can be appended to at runtime; 132 // - the module path at runtime can be a superset of the one specified during AOTCache creation. 133 134 class AOTClassLocationConfig : public CHeapObj<mtClassShared> { 135 using Group = AOTClassLocation::Group; 136 using GrowableClassLocationArray = GrowableArrayCHeap<AOTClassLocation*, mtClassShared>; 137 138 // Note: both of the following are non-null if we are dumping a dynamic archive. 139 static AOTClassLocationConfig* _dumptime_instance; 140 static const AOTClassLocationConfig* _runtime_instance; 141 142 Array<AOTClassLocation*>* _class_locations; // jrt -> -Xbootclasspath/a -> -classpath -> --module_path 143 static Array<ClassPathZipEntry*>* _dumptime_jar_files; 144 145 int _boot_classpath_end; 146 int _app_classpath_end; 147 int _module_end; 148 bool _has_non_jar_modules; 149 bool _has_platform_classes; 150 bool _has_app_classes; 151 int _max_used_index; 152 size_t _dumptime_lcp_len; 153 154 // accessors 155 Array<AOTClassLocation*>* class_locations() const { return _class_locations; } 156 157 void parse(JavaThread* current, GrowableClassLocationArray& tmp_array, ClassLocationStream& css, 158 Group group, bool parse_manifest); 159 void add_class_location(JavaThread* current, GrowableClassLocationArray& tmp_array, const char* path, 160 Group group, bool parse_manifest, bool from_cpattr); 161 void dumptime_init_helper(TRAPS); 162 163 bool check_classpaths(bool is_boot_classpath, bool has_aot_linked_classes, 164 int index_start, int index_end, ClassLocationStream& runtime_css, 165 bool use_lcp_match, const char* runtime_lcp, size_t runtime_lcp_len) const; 166 bool check_module_paths(bool has_aot_linked_classes, int index_start, int index_end, ClassLocationStream& runtime_css, 167 bool* has_extra_module_paths) const; 168 bool file_exists(const char* filename) const; 169 bool check_paths_existence(ClassLocationStream& runtime_css) const; 170 171 static const char* substitute(const char* path, size_t remove_prefix_len, 172 const char* prepend, size_t prepend_len); 173 static const char* find_lcp(ClassLocationStream& css, size_t& lcp_len); 174 bool need_lcp_match(AllClassLocationStreams& all_css) const; 175 bool need_lcp_match_helper(int start, int end, ClassLocationStream& css) const; 176 177 template <typename FUNC> void dumptime_iterate_helper(FUNC func) const { 178 assert(_class_locations != nullptr, "sanity"); 179 int n = _class_locations->length(); 180 for (int i = 0; i < n; i++) { 181 if (!func(_class_locations->at(i))) { 182 break; 183 } 184 } 185 } 186 187 template <typename FUNC> void iterate(FUNC func) const { 188 int n = class_locations()->length(); 189 for (int i = 0; i < n; i++) { 190 if (!func(class_locations()->at(i))) { 191 break; 192 } 193 } 194 } 195 196 void check_nonempty_dirs() const; 197 bool need_to_check_app_classpath() const { 198 return (num_app_classpaths() > 0) && (_max_used_index >= app_cp_start_index()) && has_platform_or_app_classes(); 199 } 200 201 void print_dumptime_classpath(LogStream& ls, int index_start, int index_limit, 202 bool do_substitute, size_t remove_prefix_len, 203 const char* prepend, size_t prepend_len) const; 204 public: 205 static AOTClassLocationConfig* dumptime() { 206 assert(_dumptime_instance != nullptr, "can only be called when dumping an AOT cache"); 207 return _dumptime_instance; 208 } 209 210 static const AOTClassLocationConfig* runtime() { 211 assert(_runtime_instance != nullptr, "can only be called when using an AOT cache"); 212 return _runtime_instance; 213 } 214 215 // Common accessors 216 int boot_cp_start_index() const { return 1; } 217 int boot_cp_end_index() const { return _boot_classpath_end; } 218 int app_cp_start_index() const { return boot_cp_end_index(); } 219 int app_cp_end_index() const { return _app_classpath_end; } 220 int module_path_start_index() const { return app_cp_end_index(); } 221 int module_path_end_index() const { return _module_end; } 222 bool has_platform_or_app_classes() const { return _has_app_classes || _has_platform_classes; } 223 bool has_non_jar_modules() const { return _has_non_jar_modules; } 224 int num_boot_classpaths() const { return boot_cp_end_index() - boot_cp_start_index(); } 225 int num_app_classpaths() const { return app_cp_end_index() - app_cp_start_index(); } 226 int num_module_paths() const { return module_path_end_index() - module_path_start_index(); } 227 228 int length() const { 229 return _class_locations->length(); 230 } 231 232 const AOTClassLocation* class_location_at(int index) const; 233 int get_module_shared_path_index(Symbol* location) const; 234 235 // Functions used only during dumptime 236 static void dumptime_init(JavaThread* current); 237 238 static void dumptime_set_has_app_classes() { 239 _dumptime_instance->_has_app_classes = true; 240 } 241 242 static void dumptime_set_has_platform_classes() { 243 _dumptime_instance->_has_platform_classes = true; 244 } 245 246 static void dumptime_update_max_used_index(int index) { 247 if (_dumptime_instance == nullptr) { 248 assert(index == 0, "sanity"); 249 } else if (_dumptime_instance->_max_used_index < index) { 250 _dumptime_instance->_max_used_index = index; 251 } 252 } 253 254 static void dumptime_check_nonempty_dirs() { 255 _dumptime_instance->check_nonempty_dirs(); 256 } 257 258 static bool dumptime_is_ready() { 259 return _dumptime_instance != nullptr; 260 } 261 template <typename FUNC> static void dumptime_iterate(FUNC func) { 262 _dumptime_instance->dumptime_iterate_helper(func); 263 } 264 265 AOTClassLocationConfig* write_to_archive() const; 266 267 // Functions used only during runtime 268 bool validate(bool has_aot_linked_classes, bool* has_extra_module_paths) const; 269 270 void check_invalid_classpath_index(int classpath_index, InstanceKlass* ik); 271 }; 272 273 274 #endif // SHARE_CDS_AOTCLASSLOCATION_HPP