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