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 74 public: 75 static const char* ARRAY_TAG; 76 77 static const char* CLASS_REFLECTION_DATA_TAG; 78 static const char* LOADER_NEGATIVE_CACHE_TAG; 79 80 enum ParseMode { 81 _parse_all, 82 _parse_lambda_forms_invokers_only, 83 }; 84 85 private: 86 // Must be C_HEAP allocated -- we don't want nested resource allocations. 87 typedef ResizeableResourceHashtable<int, InstanceKlass*, 88 AnyObj::C_HEAP, mtClassShared> ID2KlassTable; 89 90 enum { 91 _unspecified = -999, 92 }; 93 94 // Use a small initial size in debug build to test resizing logic 95 static const int INITIAL_TABLE_SIZE = DEBUG_ONLY(17) NOT_DEBUG(1987); 96 static const int MAX_TABLE_SIZE = 61333; 97 static volatile Thread* _parsing_thread; // the thread that created _instance 98 static ClassListParser* _instance; // the singleton. 99 const char* _classlist_file; 100 101 ID2KlassTable _id2klass_table; 102 103 FileInput _file_input; 104 inputStream _input_stream; 105 char* _line; // The buffer that holds the current line. Some characters in 106 // the buffer may be overwritten by '\0' during parsing. 107 int _line_len; // Original length of the input line. 108 const char* _class_name; 109 GrowableArray<const char*>* _indy_items; // items related to invoke dynamic for archiving lambda proxy classes 110 int _id; 111 int _super; 112 GrowableArray<int>* _interfaces; 113 bool _interfaces_specified; 114 const char* _source; 115 ParseMode _parse_mode; 116 117 bool parse_int_option(const char* option_name, int* value); 118 bool parse_uint_option(const char* option_name, int* value); 119 InstanceKlass* load_class_from_source(Symbol* class_name, TRAPS); 120 ID2KlassTable* id2klass_table() { 121 return &_id2klass_table; 122 } 123 InstanceKlass* lookup_class_by_id(int id); 124 void print_specified_interfaces(); 125 void print_actual_interfaces(InstanceKlass *ik); 126 bool is_matching_cp_entry(const constantPoolHandle &pool, int cp_index, TRAPS); 127 128 InstanceKlass* find_builtin_class_helper(JavaThread* current, Symbol* class_name_symbol, oop class_loader_oop); 129 InstanceKlass* find_builtin_class(JavaThread* current, const char* class_name); 130 131 void resolve_indy(JavaThread* current, Symbol* class_name_symbol); 132 void resolve_indy_impl(Symbol* class_name_symbol, TRAPS); 133 void clean_up_input_line(); 134 void read_class_name_and_attributes(); 135 void parse_class_name_and_attributes(TRAPS); 136 Klass* load_current_class(Symbol* class_name_symbol, TRAPS); 137 void parse_constant_pool_tag(); 138 void parse_class_reflection_data_tag(); 139 void parse_dynamic_proxy_tag(); 140 void parse_loader_negative_cache_tag(); 141 void parse_array_dimension_tag(); 142 143 size_t lineno() { return _input_stream.lineno(); } 144 FILE* do_open(const char* file); 145 ClassListParser(const char* file, ParseMode _parse_mode); 146 ~ClassListParser(); 147 void print_diagnostic_info(outputStream* st, const char* msg, va_list ap) ATTRIBUTE_PRINTF(3, 0); 148 void print_diagnostic_info(outputStream* st, const char* msg, ...) ATTRIBUTE_PRINTF(3, 0); 149 void constant_pool_resolution_warning(const char* msg, ...) ATTRIBUTE_PRINTF(2, 0); 150 void error(const char* msg, ...) ATTRIBUTE_PRINTF(2, 0); 151 oop loader_from_type(const char* loader_name); 152 153 public: 154 static void parse_classlist(const char* classlist_path, ParseMode parse_mode, TRAPS) { 155 ClassListParser parser(classlist_path, parse_mode); 156 parser.parse(THREAD); 157 } 158 159 static bool is_parsing_thread(); 160 static ClassListParser* instance() { 161 assert(is_parsing_thread(), "call this only in the thread that created ClassListParsing::_instance"); 162 assert(_instance != nullptr, "must be"); 163 return _instance; 164 } 165 static const char* lambda_proxy_tag() { 166 return LAMBDA_PROXY_TAG; 167 } 168 static const char* lambda_form_tag() { 169 return LAMBDA_FORM_TAG; 170 } 171 172 void parse(TRAPS); 173 void split_tokens_by_whitespace(int offset, GrowableArray<const char*>* items); 174 int split_at_tag_from_line(); 175 void parse_at_tags(TRAPS); 176 char* _token; 177 void parse_int(int* value); 178 void parse_uint(int* value); 179 bool try_parse_uint(int* value); 180 bool skip_token(const char* option_name); 181 void skip_whitespaces(); 182 void skip_non_whitespaces(); 183 184 bool parse_lambda_forms_invokers_only() { 185 return _parse_mode == _parse_lambda_forms_invokers_only; 186 } 187 bool is_id_specified() { 188 return _id != _unspecified; 189 } 190 bool is_super_specified() { 191 return _super != _unspecified; 192 } 193 bool are_interfaces_specified() { 194 return _interfaces->length() > 0; 195 } 196 int id() { 197 assert(is_id_specified(), "do not query unspecified id"); 198 return _id; 199 } 200 int super() { 201 assert(is_super_specified(), "do not query unspecified super"); 202 return _super; 203 } 204 void check_already_loaded(const char* which, int id) { 205 if (!id2klass_table()->contains(id)) { 206 error("%s id %d is not yet loaded", which, id); 207 } 208 } 209 void check_class_name(const char* class_name); 210 211 const char* current_class_name() { 212 return _class_name; 213 } 214 215 bool is_loading_from_source(); 216 217 // Look up the super or interface of the current class being loaded 218 // (in this->load_current_class()). 219 InstanceKlass* lookup_super_for_current_class(Symbol* super_name); 220 InstanceKlass* lookup_interface_for_current_class(Symbol* interface_name); 221 222 static void populate_cds_indy_info(const constantPoolHandle &pool, int cp_index, CDSIndyInfo* cii, TRAPS); 223 }; 224 #endif // SHARE_CDS_CLASSLISTPARSER_HPP