1 /* 2 * Copyright (c) 2015, 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 * 23 */ 24 25 #ifndef SHARE_CDS_CLASSLISTPARSER_HPP 26 #define SHARE_CDS_CLASSLISTPARSER_HPP 27 28 #include "interpreter/bytecodes.hpp" 29 #include "utilities/exceptions.hpp" 30 #include "utilities/globalDefinitions.hpp" 31 #include "utilities/growableArray.hpp" 32 #include "utilities/istream.hpp" 33 #include "utilities/resizeableResourceHash.hpp" 34 35 class constantPoolHandle; 36 class Thread; 37 38 class CDSIndyInfo { 39 GrowableArray<const char*>* _items; 40 public: 41 CDSIndyInfo() : _items(nullptr) {} 42 void add_item(const char* item) { 43 if (_items == nullptr) { 44 _items = new GrowableArray<const char*>(9); 45 } 46 assert(_items != nullptr, "sanity"); 47 _items->append(item); 48 } 49 void add_ref_kind(int ref_kind) { 50 switch (ref_kind) { 51 case JVM_REF_getField : _items->append("REF_getField"); break; 52 case JVM_REF_getStatic : _items->append("REF_getStatic"); break; 53 case JVM_REF_putField : _items->append("REF_putField"); break; 54 case JVM_REF_putStatic : _items->append("REF_putStatic"); break; 55 case JVM_REF_invokeVirtual : _items->append("REF_invokeVirtual"); break; 56 case JVM_REF_invokeStatic : _items->append("REF_invokeStatic"); break; 57 case JVM_REF_invokeSpecial : _items->append("REF_invokeSpecial"); break; 58 case JVM_REF_newInvokeSpecial : _items->append("REF_newInvokeSpecial"); break; 59 case JVM_REF_invokeInterface : _items->append("REF_invokeInterface"); break; 60 default : ShouldNotReachHere(); 61 } 62 } 63 GrowableArray<const char*>* items() { 64 return _items; 65 } 66 }; 67 68 class ClassListParser : public StackObj { 69 static const char* CONSTANT_POOL_TAG; 70 static const char* DYNAMIC_PROXY_TAG; 71 static const char* LAMBDA_FORM_TAG; 72 static const char* LAMBDA_PROXY_TAG; 73 public: 74 static const char* ARRAY_TAG; 75 76 static const char* CLASS_REFLECTION_DATA_TAG; 77 static const char* LOADER_NEGATIVE_CACHE_TAG; 78 79 enum ParseMode { 80 _parse_all, 81 _parse_lambda_forms_invokers_only, 82 }; 83 84 private: 85 // Must be C_HEAP allocated -- we don't want nested resource allocations. 86 typedef ResizeableResourceHashtable<int, InstanceKlass*, 87 AnyObj::C_HEAP, mtClassShared> ID2KlassTable; 88 89 enum { 90 _unspecified = -999, 91 }; 92 93 // Use a small initial size in debug build to test resizing logic 94 static const int INITIAL_TABLE_SIZE = DEBUG_ONLY(17) NOT_DEBUG(1987); 95 static const int MAX_TABLE_SIZE = 61333; 96 static volatile Thread* _parsing_thread; // the thread that created _instance 97 static ClassListParser* _instance; // the singleton. 98 const char* _classlist_file; 99 100 ID2KlassTable _id2klass_table; 101 102 FileInput _file_input; 103 inputStream _input_stream; 104 char* _line; // The buffer that holds the current line. Some characters in 105 // the buffer may be overwritten by '\0' during parsing. 106 int _line_len; // Original length of the input line. 107 const char* _class_name; 108 GrowableArray<const char*>* _indy_items; // items related to invoke dynamic for archiving lambda proxy classes 109 int _id; 110 int _super; 111 GrowableArray<int>* _interfaces; 112 bool _interfaces_specified; 113 const char* _source; 114 ParseMode _parse_mode; 115 116 bool parse_int_option(const char* option_name, int* value); 117 bool parse_uint_option(const char* option_name, int* value); 118 InstanceKlass* load_class_from_source(Symbol* class_name, TRAPS); 119 ID2KlassTable* id2klass_table() { 120 return &_id2klass_table; 121 } 122 InstanceKlass* lookup_class_by_id(int id); 123 void print_specified_interfaces(); 124 void print_actual_interfaces(InstanceKlass *ik); 125 bool is_matching_cp_entry(const constantPoolHandle &pool, int cp_index, TRAPS); 126 127 InstanceKlass* find_builtin_class_helper(JavaThread* current, Symbol* class_name_symbol, oop class_loader_oop); 128 InstanceKlass* find_builtin_class(JavaThread* current, const char* class_name); 129 130 void resolve_indy(JavaThread* current, Symbol* class_name_symbol); 131 void resolve_indy_impl(Symbol* class_name_symbol, TRAPS); 132 void clean_up_input_line(); 133 void read_class_name_and_attributes(); 134 void parse_class_name_and_attributes(TRAPS); 135 Klass* load_current_class(Symbol* class_name_symbol, TRAPS); 136 void parse_constant_pool_tag(); 137 void parse_class_reflection_data_tag(); 138 void parse_dynamic_proxy_tag(); 139 void parse_loader_negative_cache_tag(); 140 void parse_array_dimension_tag(); 141 142 size_t lineno() { return _input_stream.lineno(); } 143 FILE* do_open(const char* file); 144 ClassListParser(const char* file, ParseMode _parse_mode); 145 ~ClassListParser(); 146 void print_diagnostic_info(outputStream* st, const char* msg, va_list ap) ATTRIBUTE_PRINTF(3, 0); 147 void print_diagnostic_info(outputStream* st, const char* msg, ...) ATTRIBUTE_PRINTF(3, 0); 148 void constant_pool_resolution_warning(const char* msg, ...) ATTRIBUTE_PRINTF(2, 0); 149 void error(const char* msg, ...) ATTRIBUTE_PRINTF(2, 0); 150 oop loader_from_type(const char* loader_name); 151 public: 152 static void parse_classlist(const char* classlist_path, ParseMode parse_mode, TRAPS) { 153 ClassListParser parser(classlist_path, parse_mode); 154 parser.parse(THREAD); 155 } 156 157 static bool is_parsing_thread(); 158 static ClassListParser* instance() { 159 assert(is_parsing_thread(), "call this only in the thread that created ClassListParsing::_instance"); 160 assert(_instance != nullptr, "must be"); 161 return _instance; 162 } 163 static const char* lambda_proxy_tag() { 164 return LAMBDA_PROXY_TAG; 165 } 166 static const char* lambda_form_tag() { 167 return LAMBDA_FORM_TAG; 168 } 169 170 void parse(TRAPS); 171 void split_tokens_by_whitespace(int offset, GrowableArray<const char*>* items); 172 int split_at_tag_from_line(); 173 void parse_at_tags(TRAPS); 174 char* _token; 175 void parse_int(int* value); 176 void parse_uint(int* value); 177 bool try_parse_uint(int* value); 178 bool skip_token(const char* option_name); 179 void skip_whitespaces(); 180 void skip_non_whitespaces(); 181 182 bool parse_lambda_forms_invokers_only() { 183 return _parse_mode == _parse_lambda_forms_invokers_only; 184 } 185 bool is_id_specified() { 186 return _id != _unspecified; 187 } 188 bool is_super_specified() { 189 return _super != _unspecified; 190 } 191 bool are_interfaces_specified() { 192 return _interfaces->length() > 0; 193 } 194 int id() { 195 assert(is_id_specified(), "do not query unspecified id"); 196 return _id; 197 } 198 int super() { 199 assert(is_super_specified(), "do not query unspecified super"); 200 return _super; 201 } 202 void check_already_loaded(const char* which, int id) { 203 if (!id2klass_table()->contains(id)) { 204 error("%s id %d is not yet loaded", which, id); 205 } 206 } 207 void check_class_name(const char* class_name); 208 209 const char* current_class_name() { 210 return _class_name; 211 } 212 213 bool is_loading_from_source(); 214 215 // Look up the super or interface of the current class being loaded 216 // (in this->load_current_class()). 217 InstanceKlass* lookup_super_for_current_class(Symbol* super_name); 218 InstanceKlass* lookup_interface_for_current_class(Symbol* interface_name); 219 220 static void populate_cds_indy_info(const constantPoolHandle &pool, int cp_index, CDSIndyInfo* cii, TRAPS); 221 }; 222 #endif // SHARE_CDS_CLASSLISTPARSER_HPP