Skip to content

Commit dede353

Browse files
committed
8355798: Implement JEP 514: Ahead-of-Time Command Line Ergonomics
Reviewed-by: erikj, kvn, asmehra
1 parent b7f0f48 commit dede353

File tree

25 files changed

+1278
-173
lines changed

25 files changed

+1278
-173
lines changed

doc/testing.html

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ <h1 class="title">Testing the JDK</h1>
7272
<li><a href="#non-us-locale" id="toc-non-us-locale">Non-US
7373
locale</a></li>
7474
<li><a href="#pkcs11-tests" id="toc-pkcs11-tests">PKCS11 Tests</a></li>
75+
<li><a href="#testing-ahead-of-time-optimizations"
76+
id="toc-testing-ahead-of-time-optimizations">Testing Ahead-of-time
77+
Optimizations</a></li>
7578
<li><a href="#testing-with-alternative-security-providers"
7679
id="toc-testing-with-alternative-security-providers">Testing with
7780
alternative security providers</a></li>
@@ -596,6 +599,37 @@ <h3 id="pkcs11-tests">PKCS11 Tests</h3>
596599
JTREG=&quot;JAVA_OPTIONS=-Djdk.test.lib.artifacts.nsslib-linux_aarch64=/path/to/NSS-libs&quot;</code></pre>
597600
<p>For more notes about the PKCS11 tests, please refer to
598601
test/jdk/sun/security/pkcs11/README.</p>
602+
<h3 id="testing-ahead-of-time-optimizations">Testing Ahead-of-time
603+
Optimizations</h3>
604+
<p>One way to improve test coverage of ahead-of-time (AOT) optimizations
605+
in the JDK is to run existing jtreg test cases in a special "AOT_JDK"
606+
mode. Example:</p>
607+
<pre><code>$ make test JTREG=&quot;AOT_JDK=onestep&quot; \
608+
TEST=open/test/hotspot/jtreg/runtime/invokedynamic</code></pre>
609+
<p>In this testing mode, we first perform an AOT training run (see
610+
https://openjdk.org/jeps/483) of a special test program (<a
611+
href="../test/setup_aot/TestSetupAOT.java">test/setup_aot/TestSetupAOT.java</a>)
612+
that accesses about 5,0000 classes in the JDK core libraries.
613+
Optimization artifacts for these classes (such as pre-linked lambda
614+
expressions, execution profiles, and pre-generated native code) are
615+
stored into an AOT cache file, which will be used by all the JVMs
616+
launched by the selected jtreg test cases.</p>
617+
<p>When the jtreg tests call into the core libraries classes that are in
618+
the AOT cache, we will be able to test the AOT optimizations that were
619+
used on those classes.</p>
620+
<p>Please note that not all existing jtreg test cases can be executed
621+
with the AOT_JDK mode. See <a
622+
href="../test/hotspot/jtreg/ProblemList-AotJdk.txt">test/hotspot/jtreg/ProblemList-AotJdk.txt</a>
623+
and <a
624+
href="../test/jdk/ProblemList-AotJdk.txt">test/jdk/ProblemList-AotJdk.txt</a>.</p>
625+
<p>Also, test cases that were written specifically to test AOT, such as
626+
the tests under <a
627+
href="../test/hotspot/jtreg/runtime/cds/">test/hotspot/jtreg/runtime/cds</a>,
628+
cannot be executed with the AOT_JDK mode.</p>
629+
<p>Valid values for <code>AOT_JDK</code> are <code>onestep</code> and
630+
<code>twostep</code>. These control how the AOT cache is generated. See
631+
https://openjdk.org/jeps/514 for details. All other values are
632+
ignored.</p>
599633
<h3 id="testing-with-alternative-security-providers">Testing with
600634
alternative security providers</h3>
601635
<p>Some security tests use a hardcoded provider for

doc/testing.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,43 @@ $ make test TEST="jtreg:sun/security/pkcs11/Secmod/AddTrustedCert.java" \
611611
For more notes about the PKCS11 tests, please refer to
612612
test/jdk/sun/security/pkcs11/README.
613613

614+
### Testing Ahead-of-time Optimizations
615+
-------------------------------------------------------------------------------
616+
One way to improve test coverage of ahead-of-time (AOT) optimizations in
617+
the JDK is to run existing jtreg test cases in a special "AOT_JDK" mode.
618+
Example:
619+
620+
```
621+
$ make test JTREG="AOT_JDK=onestep" \
622+
TEST=open/test/hotspot/jtreg/runtime/invokedynamic
623+
```
624+
625+
In this testing mode, we first perform an AOT training run
626+
(see https://openjdk.org/jeps/483) of a special test program
627+
([test/setup_aot/TestSetupAOT.java](../test/setup_aot/TestSetupAOT.java))
628+
that accesses about 5,0000 classes in the JDK core libraries.
629+
Optimization artifacts for these classes (such as pre-linked
630+
lambda expressions, execution profiles, and pre-generated native code)
631+
are stored into an AOT cache file, which will be used by all the JVMs
632+
launched by the selected jtreg test cases.
633+
634+
When the jtreg tests call into the core libraries classes that are in
635+
the AOT cache, we will be able to test the AOT optimizations that were
636+
used on those classes.
637+
638+
Please note that not all existing jtreg test cases can be executed with
639+
the AOT_JDK mode. See
640+
[test/hotspot/jtreg/ProblemList-AotJdk.txt](../test/hotspot/jtreg/ProblemList-AotJdk.txt)
641+
and [test/jdk/ProblemList-AotJdk.txt](../test/jdk/ProblemList-AotJdk.txt).
642+
643+
Also, test cases that were written specifically to test AOT, such as the tests
644+
under [test/hotspot/jtreg/runtime/cds](../test/hotspot/jtreg/runtime/cds/),
645+
cannot be executed with the AOT_JDK mode.
646+
647+
Valid values for `AOT_JDK` are `onestep` and `twostep`. These control how
648+
the AOT cache is generated. See https://openjdk.org/jeps/514 for details.
649+
All other values are ignored.
650+
614651
### Testing with alternative security providers
615652

616653
Some security tests use a hardcoded provider for `KeyFactory`, `Cipher`,

make/RunTests.gmk

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,7 @@ endef
725725
# Parameter 1 is the name of the rule.
726726
#
727727
# Remaining parameters are named arguments.
728+
# TRAINING The AOT training mode: onestep or twostep
728729
# VM_OPTIONS List of JVM arguments to use when creating AOT cache
729730
#
730731
# After calling this, the following variables are defined
@@ -753,23 +754,39 @@ define SetupAOTBody
753754
$$($1_AOT_JDK_CACHE): $$(JDK_IMAGE_DIR)/release
754755
$$(call MakeDir, $$($1_AOT_JDK_OUTPUT_DIR))
755756

756-
$$(call LogWarn, AOT: Create cache configuration) \
757-
$$(call ExecuteWithLog, $$($1_AOT_JDK_OUTPUT_DIR), ( \
758-
cd $$($1_AOT_JDK_OUTPUT_DIR); \
759-
$(JAR) --extract --file $(TEST_IMAGE_DIR)/setup_aot/TestSetupAOT.jar; \
760-
$$(FIXPATH) $(JDK_UNDER_TEST)/bin/java $$($1_VM_OPTIONS) \
761-
-Xlog:class+load,aot,aot+class=debug:file=$$($1_AOT_JDK_CONF).log -Xlog:cds*=error -Xlog:aot*=error \
762-
-XX:AOTMode=record -XX:AOTConfiguration=$$($1_AOT_JDK_CONF) \
763-
TestSetupAOT $$($1_AOT_JDK_OUTPUT_DIR) > $$($1_AOT_JDK_LOG) \
764-
))
765-
766-
$$(call LogWarn, AOT: Generate AOT cache $$($1_AOT_JDK_CACHE) with flags: $$($1_VM_OPTIONS))
767-
$$(call ExecuteWithLog, $$($1_AOT_JDK_OUTPUT_DIR), ( \
768-
$$(FIXPATH) $(JDK_UNDER_TEST)/bin/java \
769-
$$($1_VM_OPTIONS) -Xlog:aot,aot+class=debug:file=$$($1_AOT_JDK_CACHE).log -Xlog:cds*=error -Xlog:aot*=error \
770-
-XX:ExtraSharedClassListFile=$(JDK_UNDER_TEST)/lib/classlist \
771-
-XX:AOTMode=create -XX:AOTConfiguration=$$($1_AOT_JDK_CONF) -XX:AOTCache=$$($1_AOT_JDK_CACHE) \
772-
))
757+
ifeq ($$($1_TRAINING), onestep)
758+
759+
$$(call LogWarn, AOT: Create AOT cache $$($1_AOT_JDK_CACHE) in one step with flags: $$($1_VM_OPTIONS)) \
760+
$$(call ExecuteWithLog, $$($1_AOT_JDK_OUTPUT_DIR), ( \
761+
cd $$($1_AOT_JDK_OUTPUT_DIR); \
762+
$(JAR) --extract --file $(TEST_IMAGE_DIR)/setup_aot/TestSetupAOT.jar; \
763+
$$(FIXPATH) $(JDK_UNDER_TEST)/bin/java $$($1_VM_OPTIONS) \
764+
-Xlog:class+load,aot,aot+class=debug:file=$$($1_AOT_JDK_CACHE).log -Xlog:cds*=error -Xlog:aot*=error \
765+
-XX:AOTMode=record -XX:AOTCacheOutput=$$($1_AOT_JDK_CACHE) \
766+
TestSetupAOT $$($1_AOT_JDK_OUTPUT_DIR) > $$($1_AOT_JDK_LOG) \
767+
))
768+
769+
else
770+
771+
$$(call LogWarn, AOT: Create cache configuration) \
772+
$$(call ExecuteWithLog, $$($1_AOT_JDK_OUTPUT_DIR), ( \
773+
cd $$($1_AOT_JDK_OUTPUT_DIR); \
774+
$(JAR) --extract --file $(TEST_IMAGE_DIR)/setup_aot/TestSetupAOT.jar; \
775+
$$(FIXPATH) $(JDK_UNDER_TEST)/bin/java $$($1_VM_OPTIONS) \
776+
-Xlog:class+load,aot,aot+class=debug:file=$$($1_AOT_JDK_CONF).log -Xlog:cds*=error -Xlog:aot*=error \
777+
-XX:AOTMode=record -XX:AOTConfiguration=$$($1_AOT_JDK_CONF) \
778+
TestSetupAOT $$($1_AOT_JDK_OUTPUT_DIR) > $$($1_AOT_JDK_LOG) \
779+
))
780+
781+
$$(call LogWarn, AOT: Generate AOT cache $$($1_AOT_JDK_CACHE) with flags: $$($1_VM_OPTIONS))
782+
$$(call ExecuteWithLog, $$($1_AOT_JDK_OUTPUT_DIR), ( \
783+
$$(FIXPATH) $(JDK_UNDER_TEST)/bin/java \
784+
$$($1_VM_OPTIONS) -Xlog:aot,aot+class=debug:file=$$($1_AOT_JDK_CACHE).log -Xlog:cds*=error -Xlog:aot*=error \
785+
-XX:ExtraSharedClassListFile=$(JDK_UNDER_TEST)/lib/classlist \
786+
-XX:AOTMode=create -XX:AOTConfiguration=$$($1_AOT_JDK_CONF) -XX:AOTCache=$$($1_AOT_JDK_CACHE) \
787+
))
788+
789+
endif
773790

774791
$1_AOT_TARGETS += $$($1_AOT_JDK_CACHE)
775792

@@ -835,7 +852,7 @@ define SetupRunJtregTestBody
835852
JTREG_RETRY_COUNT ?= 0
836853
JTREG_REPEAT_COUNT ?= 0
837854
JTREG_REPORT ?= files
838-
JTREG_AOT_JDK ?= false
855+
JTREG_AOT_JDK ?= none
839856

840857
ifneq ($$(JTREG_RETRY_COUNT), 0)
841858
ifneq ($$(JTREG_REPEAT_COUNT), 0)
@@ -975,12 +992,12 @@ define SetupRunJtregTestBody
975992
endif
976993
endif
977994

978-
ifeq ($$(JTREG_AOT_JDK), true)
995+
ifneq ($$(filter $$(JTREG_AOT_JDK), onestep twostep), )
979996
$$(call LogWarn, Add AOT target for $1)
980-
$$(eval $$(call SetupAOT, $1, VM_OPTIONS := $$(JTREG_ALL_OPTIONS) ))
981-
997+
$$(eval $$(call SetupAOT, $1, \
998+
TRAINING := $$(JTREG_AOT_JDK), \
999+
VM_OPTIONS := $$(JTREG_ALL_OPTIONS) ))
9821000
$$(call LogWarn, AOT_JDK_CACHE=$$($1_AOT_JDK_CACHE))
983-
9841001
$1_JTREG_BASIC_OPTIONS += -vmoption:-XX:AOTCache="$$($1_AOT_JDK_CACHE)"
9851002
endif
9861003

src/hotspot/share/cds/cdsConfig.cpp

Lines changed: 105 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ bool CDSConfig::_is_using_optimized_module_handling = true;
4949
bool CDSConfig::_is_dumping_full_module_graph = true;
5050
bool CDSConfig::_is_using_full_module_graph = true;
5151
bool CDSConfig::_has_aot_linked_classes = false;
52+
bool CDSConfig::_is_single_command_training = false;
53+
bool CDSConfig::_has_temp_aot_config_file = false;
5254
bool CDSConfig::_old_cds_flags_used = false;
5355
bool CDSConfig::_new_aot_flags_used = false;
5456
bool CDSConfig::_disable_heap_dumping = false;
@@ -398,12 +400,14 @@ void CDSConfig::check_aot_flags() {
398400
_old_cds_flags_used = true;
399401
}
400402

401-
// "New" AOT flags must not be mixed with "classic" flags such as -Xshare:dump
403+
// "New" AOT flags must not be mixed with "classic" CDS flags such as -Xshare:dump
402404
CHECK_NEW_FLAG(AOTCache);
405+
CHECK_NEW_FLAG(AOTCacheOutput);
403406
CHECK_NEW_FLAG(AOTConfiguration);
404407
CHECK_NEW_FLAG(AOTMode);
405408

406409
CHECK_SINGLE_PATH(AOTCache);
410+
CHECK_SINGLE_PATH(AOTCacheOutput);
407411
CHECK_SINGLE_PATH(AOTConfiguration);
408412

409413
if (FLAG_IS_DEFAULT(AOTCache) && AOTAdapterCaching) {
@@ -413,29 +417,41 @@ void CDSConfig::check_aot_flags() {
413417
log_debug(aot,codecache,init)("AOTCache is not specified - AOTStubCaching is ignored");
414418
}
415419

416-
if (FLAG_IS_DEFAULT(AOTCache) && FLAG_IS_DEFAULT(AOTConfiguration) && FLAG_IS_DEFAULT(AOTMode)) {
417-
// AOTCache/AOTConfiguration/AOTMode not used -> using the "classic CDS" workflow.
420+
bool has_cache = !FLAG_IS_DEFAULT(AOTCache);
421+
bool has_cache_output = !FLAG_IS_DEFAULT(AOTCacheOutput);
422+
bool has_config = !FLAG_IS_DEFAULT(AOTConfiguration);
423+
bool has_mode = !FLAG_IS_DEFAULT(AOTMode);
424+
425+
if (!has_cache && !has_cache_output && !has_config && !has_mode) {
426+
// AOT flags are not used. Use classic CDS workflow
418427
return;
419-
} else {
420-
_new_aot_flags_used = true;
421428
}
422429

430+
if (has_cache && has_cache_output) {
431+
vm_exit_during_initialization("Only one of AOTCache or AOTCacheOutput can be specified");
432+
}
433+
434+
if (!has_cache && (!has_mode || strcmp(AOTMode, "auto") == 0)) {
435+
if (has_cache_output) {
436+
// If AOTCacheOutput has been set, effective mode is "record".
437+
// Default value for AOTConfiguration, if necessary, will be assigned in check_aotmode_record().
438+
log_info(aot)("Selected AOTMode=record because AOTCacheOutput is specified");
439+
FLAG_SET_ERGO(AOTMode, "record");
440+
}
441+
}
442+
443+
// At least one AOT flag has been used
444+
_new_aot_flags_used = true;
445+
423446
if (FLAG_IS_DEFAULT(AOTMode) || strcmp(AOTMode, "auto") == 0 || strcmp(AOTMode, "on") == 0) {
424447
check_aotmode_auto_or_on();
425448
} else if (strcmp(AOTMode, "off") == 0) {
426449
check_aotmode_off();
450+
} else if (strcmp(AOTMode, "record") == 0) {
451+
check_aotmode_record();
427452
} else {
428-
// AOTMode is record or create
429-
if (FLAG_IS_DEFAULT(AOTConfiguration)) {
430-
vm_exit_during_initialization(err_msg("-XX:AOTMode=%s cannot be used without setting AOTConfiguration", AOTMode));
431-
}
432-
433-
if (strcmp(AOTMode, "record") == 0) {
434-
check_aotmode_record();
435-
} else {
436-
assert(strcmp(AOTMode, "create") == 0, "checked by AOTModeConstraintFunc");
437-
check_aotmode_create();
438-
}
453+
assert(strcmp(AOTMode, "create") == 0, "checked by AOTModeConstraintFunc");
454+
check_aotmode_create();
439455
}
440456

441457
// This is an old flag used by CDS regression testing only. It doesn't apply
@@ -450,7 +466,8 @@ void CDSConfig::check_aotmode_off() {
450466

451467
void CDSConfig::check_aotmode_auto_or_on() {
452468
if (!FLAG_IS_DEFAULT(AOTConfiguration)) {
453-
vm_exit_during_initialization("AOTConfiguration can only be used with -XX:AOTMode=record or -XX:AOTMode=create");
469+
vm_exit_during_initialization(err_msg("AOTConfiguration can only be used with when AOTMode is record or create (selected AOTMode = %s)",
470+
FLAG_IS_DEFAULT(AOTMode) ? "auto" : AOTMode));
454471
}
455472

456473
UseSharedSpaces = true;
@@ -462,11 +479,63 @@ void CDSConfig::check_aotmode_auto_or_on() {
462479
}
463480
}
464481

482+
// %p substitution in AOTCache, AOTCacheOutput and AOTCacheConfiguration
483+
static void substitute_aot_filename(JVMFlagsEnum flag_enum) {
484+
JVMFlag* flag = JVMFlag::flag_from_enum(flag_enum);
485+
const char* filename = flag->read<const char*>();
486+
assert(filename != nullptr, "must not have default value");
487+
488+
// For simplicity, we don't allow %p/%t to be specified twice, because make_log_name()
489+
// substitutes only the first occurrence. Otherwise, if we run with
490+
// java -XX:AOTCacheOutput=%p%p.aot
491+
// it will end up with both the pid of the training process and the assembly process.
492+
const char* first_p = strstr(filename, "%p");
493+
if (first_p != nullptr && strstr(first_p + 2, "%p") != nullptr) {
494+
vm_exit_during_initialization(err_msg("%s cannot contain more than one %%p", flag->name()));
495+
}
496+
const char* first_t = strstr(filename, "%t");
497+
if (first_t != nullptr && strstr(first_t + 2, "%t") != nullptr) {
498+
vm_exit_during_initialization(err_msg("%s cannot contain more than one %%t", flag->name()));
499+
}
500+
501+
// Note: with single-command training, %p will be the pid of the training process, not the
502+
// assembly process.
503+
const char* new_filename = make_log_name(filename, nullptr);
504+
if (strcmp(filename, new_filename) != 0) {
505+
JVMFlag::Error err = JVMFlagAccess::set_ccstr(flag, &new_filename, JVMFlagOrigin::ERGONOMIC);
506+
assert(err == JVMFlag::SUCCESS, "must never fail");
507+
}
508+
FREE_C_HEAP_ARRAY(char, new_filename);
509+
}
510+
465511
void CDSConfig::check_aotmode_record() {
512+
bool has_config = !FLAG_IS_DEFAULT(AOTConfiguration);
513+
bool has_output = !FLAG_IS_DEFAULT(AOTCacheOutput);
514+
515+
if (!has_output && !has_config) {
516+
vm_exit_during_initialization("At least one of AOTCacheOutput and AOTConfiguration must be specified when using -XX:AOTMode=record");
517+
}
518+
519+
if (has_output) {
520+
_is_single_command_training = true;
521+
substitute_aot_filename(FLAG_MEMBER_ENUM(AOTCacheOutput));
522+
if (!has_config) {
523+
// Too early; can't use resource allocation yet.
524+
size_t len = strlen(AOTCacheOutput) + 10;
525+
char* temp = AllocateHeap(len, mtArguments);
526+
jio_snprintf(temp, len, "%s.config", AOTCacheOutput);
527+
FLAG_SET_ERGO(AOTConfiguration, temp);
528+
FreeHeap(temp);
529+
_has_temp_aot_config_file = true;
530+
}
531+
}
532+
466533
if (!FLAG_IS_DEFAULT(AOTCache)) {
467534
vm_exit_during_initialization("AOTCache must not be specified when using -XX:AOTMode=record");
468535
}
469536

537+
substitute_aot_filename(FLAG_MEMBER_ENUM(AOTConfiguration));
538+
470539
UseSharedSpaces = false;
471540
RequireSharedSpaces = false;
472541
_is_dumping_static_archive = true;
@@ -478,10 +547,27 @@ void CDSConfig::check_aotmode_record() {
478547
}
479548

480549
void CDSConfig::check_aotmode_create() {
481-
if (FLAG_IS_DEFAULT(AOTCache)) {
482-
vm_exit_during_initialization("AOTCache must be specified when using -XX:AOTMode=create");
550+
if (FLAG_IS_DEFAULT(AOTConfiguration)) {
551+
vm_exit_during_initialization("AOTConfiguration must be specified when using -XX:AOTMode=create");
483552
}
484553

554+
bool has_cache = !FLAG_IS_DEFAULT(AOTCache);
555+
bool has_cache_output = !FLAG_IS_DEFAULT(AOTCacheOutput);
556+
557+
assert(!(has_cache && has_cache_output), "already checked");
558+
559+
if (!has_cache && !has_cache_output) {
560+
vm_exit_during_initialization("AOTCache or AOTCacheOutput must be specified when using -XX:AOTMode=create");
561+
}
562+
563+
if (!has_cache) {
564+
precond(has_cache_output);
565+
FLAG_SET_ERGO(AOTCache, AOTCacheOutput);
566+
}
567+
// No need to check for (!has_cache_output), as we don't look at AOTCacheOutput after here.
568+
569+
substitute_aot_filename(FLAG_MEMBER_ENUM(AOTCache));
570+
485571
_is_dumping_final_static_archive = true;
486572
UseSharedSpaces = true;
487573
RequireSharedSpaces = true;

src/hotspot/share/cds/cdsConfig.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ class CDSConfig : public AllStatic {
4141
static bool _is_dumping_full_module_graph;
4242
static bool _is_using_full_module_graph;
4343
static bool _has_aot_linked_classes;
44+
static bool _is_single_command_training;
45+
static bool _has_temp_aot_config_file;
4446

4547
const static char* _default_archive_path;
4648
const static char* _input_static_archive_path;
@@ -142,6 +144,9 @@ class CDSConfig : public AllStatic {
142144
// Misc CDS features
143145
static bool allow_only_single_java_thread() NOT_CDS_RETURN_(false);
144146

147+
static bool is_single_command_training() { return CDS_ONLY(_is_single_command_training) NOT_CDS(false); }
148+
static bool has_temp_aot_config_file() { return CDS_ONLY(_has_temp_aot_config_file) NOT_CDS(false); }
149+
145150
// This is *Legacy* optimization for lambdas before JEP 483. May be removed in the future.
146151
static bool is_dumping_lambdas_in_legacy_mode() NOT_CDS_RETURN_(false);
147152

src/hotspot/share/cds/cds_globals.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@
119119
"Cache for improving start up and warm up") \
120120
constraint(AOTCacheConstraintFunc, AtParse) \
121121
\
122+
product(ccstr, AOTCacheOutput, nullptr, \
123+
"Specifies the file name for writing the AOT cache") \
124+
\
122125
product(bool, AOTInvokeDynamicLinking, false, DIAGNOSTIC, \
123126
"AOT-link JVM_CONSTANT_InvokeDynamic entries in cached " \
124127
"ConstantPools") \

0 commit comments

Comments
 (0)