2525#include " precompiled.hpp"
2626#include " cds/archiveUtils.hpp"
2727#include " cds/classListParser.hpp"
28+ #include " cds/classPrelinker.hpp"
2829#include " cds/lambdaFormInvokers.hpp"
2930#include " cds/metaspaceShared.hpp"
3031#include " cds/unregisteredClasses.hpp"
5253#include " utilities/macros.hpp"
5354#include " utilities/utf8.hpp"
5455
56+ const char * ClassListParser::CONSTANT_POOL_TAG = " @cp" ;
57+ const char * ClassListParser::LAMBDA_FORM_TAG = " @lambda-form-invoker" ;
58+ const char * ClassListParser::LAMBDA_PROXY_TAG = " @lambda-proxy" ;
59+
5560volatile Thread* ClassListParser::_parsing_thread = nullptr ;
5661ClassListParser* ClassListParser::_instance = nullptr ;
5762
@@ -299,6 +304,9 @@ void ClassListParser::parse_at_tags(TRAPS) {
299304 }
300305 } else if (strcmp (_token, LAMBDA_FORM_TAG) == 0 ) {
301306 LambdaFormInvokers::append (os::strdup ((const char *)(_line + offset), mtInternal));
307+ } else if (strcmp (_token, CONSTANT_POOL_TAG) == 0 ) {
308+ _token = _line + offset;
309+ parse_constant_pool_tag ();
302310 } else {
303311 error (" Invalid @ tag at the beginning of line \" %s\" line #%zu" , _token, lineno ());
304312 }
@@ -395,9 +403,14 @@ void ClassListParser::print_actual_interfaces(InstanceKlass* ik) {
395403 jio_fprintf (defaultStream::error_stream (), " }\n " );
396404}
397405
398- void ClassListParser::error ( const char * msg, ...) {
406+ void ClassListParser::print_diagnostic_info (outputStream* st, const char * msg, ...) {
399407 va_list ap;
400408 va_start (ap, msg);
409+ print_diagnostic_info (st, msg, ap);
410+ va_end (ap);
411+ }
412+
413+ void ClassListParser::print_diagnostic_info (outputStream* st, const char * msg, va_list ap) {
401414 int error_index = pointer_delta_as_int (_token, _line);
402415 if (error_index >= _line_len) {
403416 error_index = _line_len - 1 ;
@@ -412,25 +425,34 @@ void ClassListParser::error(const char* msg, ...) {
412425 jio_vfprintf (defaultStream::error_stream (), msg, ap);
413426
414427 if (_line_len <= 0 ) {
415- jio_fprintf ( defaultStream::error_stream (), " \n " );
428+ st-> print ( " \n " );
416429 } else {
417- jio_fprintf ( defaultStream::error_stream (), " :\n " );
430+ st-> print ( " :\n " );
418431 for (int i=0 ; i<_line_len; i++) {
419432 char c = _line[i];
420433 if (c == ' \0 ' ) {
421- jio_fprintf ( defaultStream::error_stream (), " %s" , " " );
434+ st-> print ( " %s" , " " );
422435 } else {
423- jio_fprintf ( defaultStream::error_stream (), " %c" , c);
436+ st-> print ( " %c" , c);
424437 }
425438 }
426- jio_fprintf ( defaultStream::error_stream (), " \n " );
439+ st-> print ( " \n " );
427440 for (int i=0 ; i<error_index; i++) {
428- jio_fprintf ( defaultStream::error_stream (), " %s" , " " );
441+ st-> print ( " %s" , " " );
429442 }
430- jio_fprintf ( defaultStream::error_stream (), " ^\n " );
443+ st-> print ( " ^\n " );
431444 }
432- va_end (ap);
445+ }
433446
447+ void ClassListParser::error (const char * msg, ...) {
448+ va_list ap;
449+ va_start (ap, msg);
450+ fileStream fs (defaultStream::error_stream ());
451+ // TODO: we should write to UL/error instead, but that requires fixing some tests cases.
452+ // LogTarget(Error, cds) lt;
453+ // LogStream ls(lt);
454+ print_diagnostic_info (&fs, msg, ap);
455+ va_end (ap);
434456 vm_exit_during_initialization (" class list format error." , nullptr );
435457}
436458
@@ -453,6 +475,16 @@ void ClassListParser::check_class_name(const char* class_name) {
453475 }
454476}
455477
478+ void ClassListParser::constant_pool_resolution_warning (const char * msg, ...) {
479+ va_list ap;
480+ va_start (ap, msg);
481+ LogTarget (Warning, cds, resolve) lt;
482+ LogStream ls (lt);
483+ print_diagnostic_info (&ls, msg, ap);
484+ ls.print (" Your classlist may be out of sync with the JDK or the application." );
485+ va_end (ap);
486+ }
487+
456488// This function is used for loading classes for customized class loaders
457489// during archive dumping.
458490InstanceKlass* ClassListParser::load_class_from_source (Symbol* class_name, TRAPS) {
@@ -727,3 +759,92 @@ InstanceKlass* ClassListParser::lookup_interface_for_current_class(Symbol* inter
727759 ShouldNotReachHere ();
728760 return nullptr ;
729761}
762+
763+ InstanceKlass* ClassListParser::find_builtin_class_helper (JavaThread* current, Symbol* class_name_symbol, oop class_loader_oop) {
764+ Handle class_loader (current, class_loader_oop);
765+ Handle protection_domain;
766+ return SystemDictionary::find_instance_klass (current, class_name_symbol, class_loader, protection_domain);
767+ }
768+
769+ InstanceKlass* ClassListParser::find_builtin_class (JavaThread* current, const char * class_name) {
770+ TempNewSymbol class_name_symbol = SymbolTable::new_symbol (class_name);
771+ InstanceKlass* ik;
772+
773+ if ( (ik = find_builtin_class_helper (current, class_name_symbol, nullptr )) != nullptr
774+ || (ik = find_builtin_class_helper (current, class_name_symbol, SystemDictionary::java_platform_loader ())) != nullptr
775+ || (ik = find_builtin_class_helper (current, class_name_symbol, SystemDictionary::java_system_loader ())) != nullptr ) {
776+ return ik;
777+ } else {
778+ return nullptr ;
779+ }
780+ }
781+
782+ void ClassListParser::parse_constant_pool_tag () {
783+ if (parse_lambda_forms_invokers_only ()) {
784+ return ;
785+ }
786+
787+ JavaThread* THREAD = JavaThread::current ();
788+ skip_whitespaces ();
789+ char * class_name = _token;
790+ skip_non_whitespaces ();
791+ *_token = ' \0 ' ;
792+ _token ++;
793+
794+ InstanceKlass* ik = find_builtin_class (THREAD, class_name);
795+ if (ik == nullptr ) {
796+ _token = class_name;
797+ if (strstr (class_name, " /$Proxy" ) != nullptr ||
798+ strstr (class_name, " MethodHandle$Species_" ) != nullptr ) {
799+ // ignore -- TODO: we should filter these out in classListWriter.cpp
800+ } else {
801+ constant_pool_resolution_warning (" class %s is not (yet) loaded by one of the built-in loaders" , class_name);
802+ }
803+ return ;
804+ }
805+
806+ ResourceMark rm (THREAD);
807+ constantPoolHandle cp (THREAD, ik->constants ());
808+ GrowableArray<bool > preresolve_list (cp->length (), cp->length (), false );
809+ bool preresolve_class = false ;
810+ bool preresolve_fmi = false ;
811+ bool preresolve_indy = false ;
812+
813+ while (*_token) {
814+ int cp_index;
815+ skip_whitespaces ();
816+ parse_uint (&cp_index);
817+ if (cp_index < 1 || cp_index >= cp->length ()) {
818+ constant_pool_resolution_warning (" Invalid constant pool index %d" , cp_index);
819+ return ;
820+ } else {
821+ preresolve_list.at_put (cp_index, true );
822+ }
823+ constantTag cp_tag = cp->tag_at (cp_index);
824+ switch (cp_tag.value ()) {
825+ case JVM_CONSTANT_UnresolvedClass:
826+ preresolve_class = true ;
827+ break ;
828+ case JVM_CONSTANT_UnresolvedClassInError:
829+ case JVM_CONSTANT_Class:
830+ // ignore
831+ break ;
832+ case JVM_CONSTANT_Fieldref:
833+ preresolve_fmi = true ;
834+ break ;
835+ break ;
836+ default :
837+ constant_pool_resolution_warning (" Unsupported constant pool index %d: %s (type=%d)" ,
838+ cp_index, cp_tag.internal_name (), cp_tag.value ());
839+ return ;
840+ }
841+ }
842+
843+ if (preresolve_class) {
844+ ClassPrelinker::preresolve_class_cp_entries (THREAD, ik, &preresolve_list);
845+ }
846+ if (preresolve_fmi) {
847+ ClassPrelinker::preresolve_field_and_method_cp_entries (THREAD, ik, &preresolve_list);
848+ }
849+ }
850+
0 commit comments