1 /*
  2  * Copyright (c) 2015, 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/archiveUtils.hpp"

 27 #include "cds/classListParser.hpp"

 28 #include "cds/lambdaFormInvokers.hpp"
 29 #include "cds/metaspaceShared.hpp"
 30 #include "cds/unregisteredClasses.hpp"
 31 #include "classfile/classLoaderExt.hpp"
 32 #include "classfile/javaClasses.inline.hpp"
 33 #include "classfile/symbolTable.hpp"
 34 #include "classfile/systemDictionary.hpp"
 35 #include "classfile/systemDictionaryShared.hpp"
 36 #include "classfile/vmClasses.hpp"
 37 #include "classfile/vmSymbols.hpp"
 38 #include "interpreter/bytecode.hpp"
 39 #include "interpreter/bytecodeStream.hpp"
 40 #include "interpreter/linkResolver.hpp"
 41 #include "jimage.hpp"
 42 #include "jvm.h"
 43 #include "logging/log.hpp"
 44 #include "logging/logTag.hpp"

 45 #include "memory/resourceArea.hpp"
 46 #include "oops/constantPool.inline.hpp"

 47 #include "runtime/atomic.hpp"
 48 #include "runtime/handles.inline.hpp"
 49 #include "runtime/java.hpp"
 50 #include "runtime/javaCalls.hpp"
 51 #include "utilities/defaultStream.hpp"
 52 #include "utilities/macros.hpp"
 53 








 54 volatile Thread* ClassListParser::_parsing_thread = nullptr;
 55 ClassListParser* ClassListParser::_instance = nullptr;
 56 
 57 ClassListParser::ClassListParser(const char* file, ParseMode parse_mode) : _id2klass_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE) {

 58   log_info(cds)("Parsing %s%s", file,
 59                 (parse_mode == _parse_lambda_forms_invokers_only) ? " (lambda form invokers only)" : "");
 60   _classlist_file = file;
 61   _file = nullptr;
 62   // Use os::open() because neither fopen() nor os::fopen()
 63   // can handle long path name on Windows.
 64   int fd = os::open(file, O_RDONLY, S_IREAD);
 65   if (fd != -1) {
 66     // Obtain a File* from the file descriptor so that fgets()
 67     // can be used in parse_one_line()
 68     _file = os::fdopen(fd, "r");
 69   }
 70   if (_file == nullptr) {
 71     char errmsg[JVM_MAXPATHLEN];
 72     os::lasterror(errmsg, JVM_MAXPATHLEN);
 73     vm_exit_during_initialization("Loading classlist failed", errmsg);
 74   }

 75   _line_no = 0;
 76   _token = _line;
 77   _interfaces = new (mtClass) GrowableArray<int>(10, mtClass);
 78   _indy_items = new (mtClass) GrowableArray<const char*>(9, mtClass);
 79   _parse_mode = parse_mode;
 80 
 81   // _instance should only be accessed by the thread that created _instance.
 82   assert(_instance == nullptr, "must be singleton");
 83   _instance = this;
 84   Atomic::store(&_parsing_thread, Thread::current());
 85 }
 86 
 87 bool ClassListParser::is_parsing_thread() {
 88   return Atomic::load(&_parsing_thread) == Thread::current();
 89 }
 90 
 91 ClassListParser::~ClassListParser() {
 92   if (_file != nullptr) {
 93     fclose(_file);
 94   }
 95   Atomic::store(&_parsing_thread, (Thread*)nullptr);
 96   delete _indy_items;
 97   delete _interfaces;
 98   _instance = nullptr;
 99 }
100 
101 int ClassListParser::parse(TRAPS) {
102   int class_count = 0;
103 
104   while (parse_one_line()) {
105     if (lambda_form_line()) {
106       // The current line is "@lambda-form-invoker ...". It has been recorded in LambdaFormInvokers,
107       // and will be processed later.
108       continue;
109     }
110 








111     if (_parse_mode == _parse_lambda_forms_invokers_only) {
112       continue;
113     }
114 
115     TempNewSymbol class_name_symbol = SymbolTable::new_symbol(_class_name);
116     if (_indy_items->length() > 0) {
117       // The current line is "@lambda-proxy class_name". Load the proxy class.
118       resolve_indy(THREAD, class_name_symbol);
119       class_count++;
120       continue;
121     }
122 
123     Klass* klass = load_current_class(class_name_symbol, THREAD);
124     if (HAS_PENDING_EXCEPTION) {
125       if (PENDING_EXCEPTION->is_a(vmClasses::OutOfMemoryError_klass())) {
126         // If we have run out of memory, don't try to load the rest of the classes in
127         // the classlist. Throw an exception, which will terminate the dumping process.
128         return 0; // THROW
129       }
130 
131       ResourceMark rm(THREAD);
132       char* ex_msg = (char*)"";
133       oop message = java_lang_Throwable::message(PENDING_EXCEPTION);
134       if (message != nullptr) {
135         ex_msg = java_lang_String::as_utf8_string(message);
136       }
137       log_warning(cds)("%s: %s", PENDING_EXCEPTION->klass()->external_name(), ex_msg);
138       // We might have an invalid class name or an bad class. Warn about it
139       // and keep going to the next line.
140       CLEAR_PENDING_EXCEPTION;
141       log_warning(cds)("Preload Warning: Cannot find %s", _class_name);
142       continue;
143     }
144 
145     assert(klass != nullptr, "sanity");
146     if (log_is_enabled(Trace, cds)) {
147       ResourceMark rm(THREAD);
148       log_trace(cds)("Shared spaces preloaded: %s", klass->external_name());
149     }
150 
151     if (klass->is_instance_klass()) {
152       InstanceKlass* ik = InstanceKlass::cast(klass);
153 
154       // Link the class to cause the bytecodes to be rewritten and the
155       // cpcache to be created. The linking is done as soon as classes
156       // are loaded in order that the related data structures (klass and
157       // cpCache) are located together.
158       MetaspaceShared::try_link_class(THREAD, ik);
159     }
160 
161     class_count++;
162   }
163 
164   return class_count;
165 }
166 
167 bool ClassListParser::parse_one_line() {
168   for (;;) {
169     if (fgets(_line, sizeof(_line), _file) == nullptr) {






170       return false;
171     }
172     ++ _line_no;
173     _line_len = (int)strlen(_line);
174     if (_line_len > _max_allowed_line_len) {
175       error("input line too long (must be no longer than %d chars)", _max_allowed_line_len);
176     }
177     if (*_line == '#') { // comment
178       continue;
179     }
180 
181     {
182       int len = (int)strlen(_line);
183       int i;
184       // Replace \t\r\n\f with ' '
185       for (i=0; i<len; i++) {
186         if (_line[i] == '\t' || _line[i] == '\r' || _line[i] == '\n' || _line[i] == '\f') {
187           _line[i] = ' ';
188         }
189       }
190 
191       // Remove trailing newline/space
192       while (len > 0) {
193         if (_line[len-1] == ' ') {
194           _line[len-1] = '\0';
195           len --;
196         } else {
197           break;
198         }
199       }
200       _line_len = len;
201     }
202 
203     // valid line
204     break;
205   }
206 
207   _class_name = _line;
208   _id = _unspecified;
209   _super = _unspecified;
210   _interfaces->clear();
211   _source = nullptr;
212   _interfaces_specified = false;
213   _indy_items->clear();
214   _lambda_form_line = false;



215 
216   if (_line[0] == '@') {
217     return parse_at_tags();
218   }
219 
220   if ((_token = strchr(_line, ' ')) == nullptr) {
221     // No optional arguments are specified.
222     return true;
223   }
224 
225   // Mark the end of the name, and go to the next input char
226   *_token++ = '\0';
227 
228   while (*_token) {
229     skip_whitespaces();
230 
231     if (parse_uint_option("id:", &_id)) {
232       continue;
233     } else if (parse_uint_option("super:", &_super)) {
234       check_already_loaded("Super class", _super);
235       continue;
236     } else if (skip_token("interfaces:")) {
237       int i;
238       while (try_parse_uint(&i)) {
239         check_already_loaded("Interface", i);
240         _interfaces->append(i);
241       }
242     } else if (skip_token("source:")) {
243       skip_whitespaces();
244       _source = _token;
245       char* s = strchr(_token, ' ');
246       if (s == nullptr) {
247         break; // end of input line
248       } else {
249         *s = '\0'; // mark the end of _source
250         _token = s+1;
251       }
252     } else {
253       error("Unknown input");
254     }
255   }
256 
257   // if src is specified
258   //     id super interfaces must all be specified
259   //     loader may be specified
260   // else
261   //     # the class is loaded from classpath
262   //     id may be specified
263   //     super, interfaces, loader must not be specified
264   return true;
265 }
266 
267 void ClassListParser::split_tokens_by_whitespace(int offset) {
268   int start = offset;
269   int end;
270   bool done = false;
271   while (!done) {
272     while (_line[start] == ' ' || _line[start] == '\t') start++;
273     end = start;
274     while (_line[end] && _line[end] != ' ' && _line[end] != '\t') end++;
275     if (_line[end] == '\0') {
276       done = true;
277     } else {
278       _line[end] = '\0';
279     }
280     _indy_items->append(_line + start);
281     start = ++end;
282   }
283 }
284 
285 int ClassListParser::split_at_tag_from_line() {
286   _token = _line;
287   char* ptr;
288   if ((ptr = strchr(_line, ' ')) == nullptr) {
289     error("Too few items following the @ tag \"%s\" line #%d", _line, _line_no);
290     return 0;
291   }
292   *ptr++ = '\0';
293   while (*ptr == ' ' || *ptr == '\t') ptr++;
294   return (int)(ptr - _line);
295 }
296 
297 bool ClassListParser::parse_at_tags() {
298   assert(_line[0] == '@', "must be");
299   int offset;
300   if ((offset = split_at_tag_from_line()) == 0) {
301     return false;
302   }
303 
304   if (strcmp(_token, LAMBDA_PROXY_TAG) == 0) {
305     split_tokens_by_whitespace(offset);
306     if (_indy_items->length() < 2) {
307       error("Line with @ tag has too few items \"%s\" line #%d", _token, _line_no);
308       return false;
309     }
310     // set the class name
311     _class_name = _indy_items->at(0);
312     return true;
313   } else if (strcmp(_token, LAMBDA_FORM_TAG) == 0) {
314     LambdaFormInvokers::append(os::strdup((const char*)(_line + offset), mtInternal));
315     _lambda_form_line = true;
316     return true;

























317   } else {
318     error("Invalid @ tag at the beginning of line \"%s\" line #%d", _token, _line_no);
319     return false;
320   }
321 }
322 
323 void ClassListParser::skip_whitespaces() {
324   while (*_token == ' ' || *_token == '\t') {
325     _token ++;
326   }
327 }
328 
329 void ClassListParser::skip_non_whitespaces() {
330   while (*_token && *_token != ' ' && *_token != '\t') {
331     _token ++;
332   }
333 }
334 
335 void ClassListParser::parse_int(int* value) {
336   skip_whitespaces();
337   if (sscanf(_token, "%i", value) == 1) {
338     skip_non_whitespaces();
339   } else {
340     error("Error: expected integer");
341   }
342 }
343 
344 void ClassListParser::parse_uint(int* value) {
345   parse_int(value);
346   if (*value < 0) {
347     error("Error: negative integers not allowed (%d)", *value);
348   }
349 }
350 
351 bool ClassListParser::try_parse_uint(int* value) {
352   skip_whitespaces();
353   if (sscanf(_token, "%i", value) == 1) {
354     skip_non_whitespaces();
355     return true;
356   }
357   return false;
358 }
359 
360 bool ClassListParser::skip_token(const char* option_name) {
361   size_t len = strlen(option_name);
362   if (strncmp(_token, option_name, len) == 0) {
363     _token += len;
364     return true;
365   } else {
366     return false;
367   }
368 }
369 
370 bool ClassListParser::parse_int_option(const char* option_name, int* value) {
371   if (skip_token(option_name)) {
372     if (*value != _unspecified) {
373       error("%s specified twice", option_name);
374     } else {
375       parse_int(value);
376       return true;
377     }
378   }
379   return false;
380 }
381 
382 bool ClassListParser::parse_uint_option(const char* option_name, int* value) {
383   if (skip_token(option_name)) {
384     if (*value != _unspecified) {
385       error("%s specified twice", option_name);
386     } else {
387       parse_uint(value);
388       return true;
389     }
390   }
391   return false;
392 }
393 
394 void ClassListParser::print_specified_interfaces() {
395   const int n = _interfaces->length();
396   jio_fprintf(defaultStream::error_stream(), "Currently specified interfaces[%d] = {\n", n);
397   for (int i=0; i<n; i++) {
398     InstanceKlass* k = lookup_class_by_id(_interfaces->at(i));
399     jio_fprintf(defaultStream::error_stream(), "  %4d = %s\n", _interfaces->at(i), k->name()->as_klass_external_name());
400   }
401   jio_fprintf(defaultStream::error_stream(), "}\n");
402 }
403 
404 void ClassListParser::print_actual_interfaces(InstanceKlass* ik) {
405   int n = ik->local_interfaces()->length();
406   jio_fprintf(defaultStream::error_stream(), "Actual interfaces[%d] = {\n", n);
407   for (int i = 0; i < n; i++) {
408     InstanceKlass* e = ik->local_interfaces()->at(i);
409     jio_fprintf(defaultStream::error_stream(), "  %s\n", e->name()->as_klass_external_name());
410   }
411   jio_fprintf(defaultStream::error_stream(), "}\n");
412 }
413 
414 void ClassListParser::error(const char* msg, ...) {
415   va_list ap;
416   va_start(ap, msg);





417   int error_index = pointer_delta_as_int(_token, _line);
418   if (error_index >= _line_len) {
419     error_index = _line_len - 1;
420   }
421   if (error_index < 0) {
422     error_index = 0;
423   }
424 
425   jio_fprintf(defaultStream::error_stream(),
426               "An error has occurred while processing class list file %s %d:%d.\n",
427               _classlist_file, _line_no, (error_index + 1));
428   jio_vfprintf(defaultStream::error_stream(), msg, ap);
429 
430   if (_line_len <= 0) {
431     jio_fprintf(defaultStream::error_stream(), "\n");
432   } else {
433     jio_fprintf(defaultStream::error_stream(), ":\n");
434     for (int i=0; i<_line_len; i++) {
435       char c = _line[i];
436       if (c == '\0') {
437         jio_fprintf(defaultStream::error_stream(), "%s", " ");
438       } else {
439         jio_fprintf(defaultStream::error_stream(), "%c", c);
440       }
441     }
442     jio_fprintf(defaultStream::error_stream(), "\n");
443     for (int i=0; i<error_index; i++) {
444       jio_fprintf(defaultStream::error_stream(), "%s", " ");
445     }
446     jio_fprintf(defaultStream::error_stream(), "^\n");
447   }

448 






449   vm_exit_during_initialization("class list format error.", nullptr);
450   va_end(ap);
451 }
452 










453 // This function is used for loading classes for customized class loaders
454 // during archive dumping.
455 InstanceKlass* ClassListParser::load_class_from_source(Symbol* class_name, TRAPS) {
456 #if !(defined(_LP64) && (defined(LINUX) || defined(__APPLE__) || defined(_WINDOWS)))
457   // The only supported platforms are: (1) Linux/64-bit and (2) Solaris/64-bit and
458   // (3) MacOSX/64-bit and (4) Windowss/64-bit
459   // This #if condition should be in sync with the areCustomLoadersSupportedForCDS
460   // method in test/lib/jdk/test/lib/Platform.java.
461   error("AppCDS custom class loaders not supported on this platform");
462 #endif
463 
464   if (!is_super_specified()) {
465     error("If source location is specified, super class must be also specified");
466   }
467   if (!is_id_specified()) {
468     error("If source location is specified, id must be also specified");
469   }
470   if (strncmp(_class_name, "java/", 5) == 0) {
471     log_info(cds)("Prohibited package for non-bootstrap classes: %s.class from %s",
472           _class_name, _source);
473     THROW_NULL(vmSymbols::java_lang_ClassNotFoundException());
474   }
475 
476   InstanceKlass* k = UnregisteredClasses::load_class(class_name, _source, CHECK_NULL);
477   if (k->local_interfaces()->length() != _interfaces->length()) {
478     print_specified_interfaces();
479     print_actual_interfaces(k);
480     error("The number of interfaces (%d) specified in class list does not match the class file (%d)",
481           _interfaces->length(), k->local_interfaces()->length());
482   }
483 
484   assert(k->is_shared_unregistered_class(), "must be");
485 
486   bool added = SystemDictionaryShared::add_unregistered_class(THREAD, k);
487   if (!added) {
488     // We allow only a single unregistered class for each unique name.
489     error("Duplicated class %s", _class_name);
490   }
491 
492   return k;
493 }
494 
495 void ClassListParser::populate_cds_indy_info(const constantPoolHandle &pool, int cp_index, CDSIndyInfo* cii, TRAPS) {
496   // Caller needs to allocate ResourceMark.
497   int type_index = pool->bootstrap_name_and_type_ref_index_at(cp_index);
498   int name_index = pool->name_ref_index_at(type_index);
499   cii->add_item(pool->symbol_at(name_index)->as_C_string());
500   int sig_index = pool->signature_ref_index_at(type_index);
501   cii->add_item(pool->symbol_at(sig_index)->as_C_string());
502   int argc = pool->bootstrap_argument_count_at(cp_index);
503   if (argc > 0) {
504     for (int arg_i = 0; arg_i < argc; arg_i++) {
505       int arg = pool->bootstrap_argument_index_at(cp_index, arg_i);
506       jbyte tag = pool->tag_at(arg).value();
507       if (tag == JVM_CONSTANT_MethodType) {
508         cii->add_item(pool->method_type_signature_at(arg)->as_C_string());
509       } else if (tag == JVM_CONSTANT_MethodHandle) {
510         cii->add_ref_kind(pool->method_handle_ref_kind_at(arg));
511         int callee_index = pool->method_handle_klass_index_at(arg);
512         Klass* callee = pool->klass_at(callee_index, CHECK);
513         cii->add_item(callee->name()->as_C_string());
514         cii->add_item(pool->method_handle_name_ref_at(arg)->as_C_string());
515         cii->add_item(pool->method_handle_signature_ref_at(arg)->as_C_string());
516       } else {
517         ShouldNotReachHere();
518       }
519     }
520   }
521 }
522 
523 bool ClassListParser::is_matching_cp_entry(const constantPoolHandle &pool, int cp_index, TRAPS) {
524   ResourceMark rm(THREAD);
525   CDSIndyInfo cii;
526   populate_cds_indy_info(pool, cp_index, &cii, CHECK_0);
527   GrowableArray<const char*>* items = cii.items();
528   int indy_info_offset = 1;
529   if (_indy_items->length() - indy_info_offset != items->length()) {
530     return false;
531   }
532   for (int i = 0; i < items->length(); i++) {
533     if (strcmp(_indy_items->at(i + indy_info_offset), items->at(i)) != 0) {
534       return false;
535     }
536   }
537   return true;
538 }
539 
540 void ClassListParser::resolve_indy(JavaThread* current, Symbol* class_name_symbol) {
541   ExceptionMark em(current);
542   JavaThread* THREAD = current; // For exception macros.
543   ClassListParser::resolve_indy_impl(class_name_symbol, THREAD);
544   if (HAS_PENDING_EXCEPTION) {
545     ResourceMark rm(current);
546     char* ex_msg = (char*)"";
547     oop message = java_lang_Throwable::message(PENDING_EXCEPTION);
548     if (message != nullptr) {
549       ex_msg = java_lang_String::as_utf8_string(message);
550     }
551     log_warning(cds)("resolve_indy for class %s has encountered exception: %s %s",
552                      class_name_symbol->as_C_string(),
553                      PENDING_EXCEPTION->klass()->external_name(),
554                      ex_msg);
555     CLEAR_PENDING_EXCEPTION;
556   }
557 }
558 
559 void ClassListParser::resolve_indy_impl(Symbol* class_name_symbol, TRAPS) {
560   Handle class_loader(THREAD, SystemDictionary::java_system_loader());
561   Handle protection_domain;
562   Klass* klass = SystemDictionary::resolve_or_fail(class_name_symbol, class_loader, protection_domain, true, CHECK);
563   if (klass->is_instance_klass()) {
564     InstanceKlass* ik = InstanceKlass::cast(klass);
565     MetaspaceShared::try_link_class(THREAD, ik);
566     if (!ik->is_linked()) {
567       // Verification of ik has failed
568       return;
569     }
570 
571     ConstantPool* cp = ik->constants();
572     ConstantPoolCache* cpcache = cp->cache();
573     bool found = false;
574     for (int indy_index = 0; indy_index < cpcache->resolved_indy_entries_length(); indy_index++) {
575       int pool_index = cpcache->resolved_indy_entry_at(indy_index)->constant_pool_index();
576       constantPoolHandle pool(THREAD, cp);
577       BootstrapInfo bootstrap_specifier(pool, pool_index, indy_index);
578       Handle bsm = bootstrap_specifier.resolve_bsm(CHECK);
579       if (!SystemDictionaryShared::is_supported_invokedynamic(&bootstrap_specifier)) {
580         log_debug(cds, lambda)("is_supported_invokedynamic check failed for cp_index %d", pool_index);
581         continue;
582       }
583       bool matched = is_matching_cp_entry(pool, pool_index, CHECK);
584       if (matched) {
585         found = true;
586         CallInfo info;
587         bool is_done = bootstrap_specifier.resolve_previously_linked_invokedynamic(info, CHECK);
588         if (!is_done) {
589           // resolve it
590           Handle recv;
591           LinkResolver::resolve_invoke(info,
592                                        recv,
593                                        pool,
594                                        ConstantPool::encode_invokedynamic_index(indy_index),
595                                        Bytecodes::_invokedynamic, CHECK);
596           break;
597         }
598         cpcache->set_dynamic_call(info, indy_index);
599       }
600     }
601     if (!found) {
602       ResourceMark rm(THREAD);
603       log_warning(cds)("No invoke dynamic constant pool entry can be found for class %s. The classlist is probably out-of-date.",
604                      class_name_symbol->as_C_string());
605     }
606   }
607 }
608 
609 Klass* ClassListParser::load_current_class(Symbol* class_name_symbol, TRAPS) {
610   Klass* klass;
611   if (!is_loading_from_source()) {
612     // Load classes for the boot/platform/app loaders only.
613     if (is_super_specified()) {
614       error("If source location is not specified, super class must not be specified");
615     }
616     if (are_interfaces_specified()) {
617       error("If source location is not specified, interface(s) must not be specified");
618     }
619 
620     if (Signature::is_array(class_name_symbol)) {
621       // array classes are not supported in class list.
622       THROW_NULL(vmSymbols::java_lang_ClassNotFoundException());
623     }
624 
625     JavaValue result(T_OBJECT);
626     // Call java_system_loader().loadClass() directly, which will
627     // delegate to the correct loader (boot, platform or app) depending on
628     // the package name.
629 
630     // ClassLoader.loadClass() wants external class name format, i.e., convert '/' chars to '.'
631     Handle ext_class_name = java_lang_String::externalize_classname(class_name_symbol, CHECK_NULL);
632     Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
633 
634     JavaCalls::call_virtual(&result,
635                             loader, //SystemDictionary::java_system_loader(),
636                             vmClasses::ClassLoader_klass(),
637                             vmSymbols::loadClass_name(),
638                             vmSymbols::string_class_signature(),
639                             ext_class_name,
640                             CHECK_NULL);
641 
642     assert(result.get_type() == T_OBJECT, "just checking");
643     oop obj = result.get_oop();
644     assert(obj != nullptr, "jdk.internal.loader.BuiltinClassLoader::loadClass never returns null");
645     klass = java_lang_Class::as_Klass(obj);
646   } else {
647     // If "source:" tag is specified, all super class and super interfaces must be specified in the
648     // class list file.
649     klass = load_class_from_source(class_name_symbol, CHECK_NULL);
650   }
651 
652   assert(klass != nullptr, "exception should have been thrown");
653   assert(klass->is_instance_klass(), "array classes should have been filtered out");
654 
655   if (is_id_specified()) {
656     InstanceKlass* ik = InstanceKlass::cast(klass);
657     int id = this->id();
658     SystemDictionaryShared::update_shared_entry(ik, id);
659     bool created;
660     id2klass_table()->put_if_absent(id, ik, &created);
661     if (!created) {
662       error("Duplicated ID %d for class %s", id, _class_name);
663     }
664     if (id2klass_table()->maybe_grow()) {
665       log_info(cds, hashtables)("Expanded id2klass_table() to %d", id2klass_table()->table_size());
666     }
667   }
668 
669   return klass;
670 }
671 
672 bool ClassListParser::is_loading_from_source() {
673   return (_source != nullptr);
674 }
675 
676 InstanceKlass* ClassListParser::lookup_class_by_id(int id) {
677   InstanceKlass** klass_ptr = id2klass_table()->get(id);
678   if (klass_ptr == nullptr) {
679     error("Class ID %d has not been defined", id);
680   }
681   assert(*klass_ptr != nullptr, "must be");
682   return *klass_ptr;
683 }
684 
685 
686 InstanceKlass* ClassListParser::lookup_super_for_current_class(Symbol* super_name) {
687   if (!is_loading_from_source()) {
688     return nullptr;
689   }
690 
691   InstanceKlass* k = lookup_class_by_id(super());
692   if (super_name != k->name()) {
693     error("The specified super class %s (id %d) does not match actual super class %s",
694           k->name()->as_klass_external_name(), super(),
695           super_name->as_klass_external_name());
696   }
697   return k;
698 }
699 
700 InstanceKlass* ClassListParser::lookup_interface_for_current_class(Symbol* interface_name) {
701   if (!is_loading_from_source()) {
702     return nullptr;
703   }
704 
705   const int n = _interfaces->length();
706   if (n == 0) {
707     error("Class %s implements the interface %s, but no interface has been specified in the input line",
708           _class_name, interface_name->as_klass_external_name());
709     ShouldNotReachHere();
710   }
711 
712   int i;
713   for (i=0; i<n; i++) {
714     InstanceKlass* k = lookup_class_by_id(_interfaces->at(i));
715     if (interface_name == k->name()) {
716       return k;
717     }
718   }
719 
720   // interface_name is not specified by the "interfaces:" keyword.
721   print_specified_interfaces();
722   error("The interface %s implemented by class %s does not match any of the specified interface IDs",
723         interface_name->as_klass_external_name(), _class_name);
724   ShouldNotReachHere();
725   return nullptr;
726 }














































































































































































































































































































--- EOF ---