8207263: Store the Configuration for system modules into CDS archive

Archive boot layer Configuration.

Reviewed-by: redestad, iklam, ccheung
This commit is contained in:
Jiangli Zhou 2018-08-10 00:35:57 -04:00
parent 5858a507f4
commit a5d14313f5
13 changed files with 353 additions and 45 deletions

View File

@ -4250,6 +4250,11 @@ int reflect_UnsafeStaticFieldAccessorImpl::_base_offset;
int jdk_internal_module_ArchivedModuleGraph::_archivedSystemModules_offset;
int jdk_internal_module_ArchivedModuleGraph::_archivedModuleFinder_offset;
int jdk_internal_module_ArchivedModuleGraph::_archivedMainModule_offset;
int jdk_internal_module_ArchivedModuleGraph::_archivedConfiguration_offset;
int java_lang_module_Configuration::_EMPTY_CONFIGURATION_offset;
int java_util_ImmutableCollections_ListN::_EMPTY_LIST_offset;
int java_util_ImmutableCollections_SetN::_EMPTY_SET_offset;
int java_util_ImmutableCollections_MapN::_EMPTY_MAP_offset;
#define STACKTRACEELEMENT_FIELDS_DO(macro) \
macro(declaringClassObject_offset, k, "declaringClassObject", class_signature, false); \
@ -4412,20 +4417,81 @@ static int member_offset(int hardcoded_offset) {
return (hardcoded_offset * heapOopSize) + instanceOopDesc::base_offset_in_bytes();
}
#define MODULEBOOTSTRAP_FIELDS_DO(macro) \
#define ARCHIVEDMODULEGRAPH_FIELDS_DO(macro) \
macro(_archivedSystemModules_offset, k, "archivedSystemModules", systemModules_signature, true); \
macro(_archivedModuleFinder_offset, k, "archivedModuleFinder", moduleFinder_signature, true); \
macro(_archivedMainModule_offset, k, "archivedMainModule", string_signature, true)
macro(_archivedMainModule_offset, k, "archivedMainModule", string_signature, true); \
macro(_archivedConfiguration_offset, k, "archivedConfiguration", configuration_signature, true)
void jdk_internal_module_ArchivedModuleGraph::compute_offsets() {
InstanceKlass* k = SystemDictionary::ArchivedModuleGraph_klass();
assert(k != NULL, "must be loaded");
MODULEBOOTSTRAP_FIELDS_DO(FIELD_COMPUTE_OFFSET);
ARCHIVEDMODULEGRAPH_FIELDS_DO(FIELD_COMPUTE_OFFSET);
}
#if INCLUDE_CDS
void jdk_internal_module_ArchivedModuleGraph::serialize(SerializeClosure* f) {
MODULEBOOTSTRAP_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
ARCHIVEDMODULEGRAPH_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
#define CONFIGURATION_FIELDS_DO(macro) \
macro(_EMPTY_CONFIGURATION_offset, k, "EMPTY_CONFIGURATION", configuration_signature, true)
void java_lang_module_Configuration::compute_offsets() {
InstanceKlass* k = SystemDictionary::Configuration_klass();
assert(k != NULL, "must be loaded");
CONFIGURATION_FIELDS_DO(FIELD_COMPUTE_OFFSET);
}
#if INCLUDE_CDS
void java_lang_module_Configuration::serialize(SerializeClosure* f) {
CONFIGURATION_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
#define LISTN_FIELDS_DO(macro) \
macro(_EMPTY_LIST_offset, k, "EMPTY_LIST", list_signature, true)
void java_util_ImmutableCollections_ListN::compute_offsets() {
InstanceKlass* k = SystemDictionary::ImmutableCollections_ListN_klass();
assert(k != NULL, "must be loaded");
LISTN_FIELDS_DO(FIELD_COMPUTE_OFFSET);
}
#if INCLUDE_CDS
void java_util_ImmutableCollections_ListN::serialize(SerializeClosure* f) {
LISTN_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
#define SETN_FIELDS_DO(macro) \
macro(_EMPTY_SET_offset, k, "EMPTY_SET", set_signature, true)
void java_util_ImmutableCollections_SetN::compute_offsets() {
InstanceKlass* k = SystemDictionary::ImmutableCollections_SetN_klass();
assert(k != NULL, "must be loaded");
SETN_FIELDS_DO(FIELD_COMPUTE_OFFSET);
}
#if INCLUDE_CDS
void java_util_ImmutableCollections_SetN::serialize(SerializeClosure* f) {
SETN_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
#define MAPN_FIELDS_DO(macro) \
macro(_EMPTY_MAP_offset, k, "EMPTY_MAP", map_signature, true)
void java_util_ImmutableCollections_MapN::compute_offsets() {
InstanceKlass* k = SystemDictionary::ImmutableCollections_MapN_klass();
assert(k != NULL, "must be loaded");
MAPN_FIELDS_DO(FIELD_COMPUTE_OFFSET);
}
#if INCLUDE_CDS
void java_util_ImmutableCollections_MapN::serialize(SerializeClosure* f) {
MAPN_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif
@ -4487,6 +4553,10 @@ void JavaClasses::compute_offsets() {
java_lang_LiveStackFrameInfo::compute_offsets();
java_util_concurrent_locks_AbstractOwnableSynchronizer::compute_offsets();
java_lang_module_Configuration::compute_offsets();
java_util_ImmutableCollections_ListN::compute_offsets();
java_util_ImmutableCollections_MapN::compute_offsets();
java_util_ImmutableCollections_SetN::compute_offsets();
jdk_internal_module_ArchivedModuleGraph::compute_offsets();
// generated interpreter code wants to know about the offsets we just computed:

View File

@ -1490,10 +1490,48 @@ class jdk_internal_module_ArchivedModuleGraph: AllStatic {
static int _archivedSystemModules_offset;
static int _archivedModuleFinder_offset;
static int _archivedMainModule_offset;
static int _archivedConfiguration_offset;
public:
static int archivedSystemModules_offset() { return _archivedSystemModules_offset; }
static int archivedModuleFinder_offset() { return _archivedModuleFinder_offset; }
static int archivedMainModule_offset() { return _archivedMainModule_offset; }
static int archivedConfiguration_offset() { return _archivedConfiguration_offset; }
static void compute_offsets();
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
};
class java_lang_module_Configuration: AllStatic {
private:
static int _EMPTY_CONFIGURATION_offset;
public:
static int EMPTY_CONFIGURATION_offset() { return _EMPTY_CONFIGURATION_offset; }
static void compute_offsets();
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
};
class java_util_ImmutableCollections_ListN : AllStatic {
private:
static int _EMPTY_LIST_offset;
public:
static int EMPTY_LIST_offset() { return _EMPTY_LIST_offset; }
static void compute_offsets();
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
};
class java_util_ImmutableCollections_SetN : AllStatic {
private:
static int _EMPTY_SET_offset;
public:
static int EMPTY_SET_offset() { return _EMPTY_SET_offset; }
static void compute_offsets();
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
};
class java_util_ImmutableCollections_MapN : AllStatic {
private:
static int _EMPTY_MAP_offset;
public:
static int EMPTY_MAP_offset() { return _EMPTY_MAP_offset; }
static void compute_offsets();
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
};

View File

@ -187,6 +187,10 @@ class OopStorage;
do_klass(jdk_internal_loader_ClassLoaders_AppClassLoader_klass, jdk_internal_loader_ClassLoaders_AppClassLoader, Pre ) \
do_klass(jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass, jdk_internal_loader_ClassLoaders_PlatformClassLoader, Pre ) \
do_klass(CodeSource_klass, java_security_CodeSource, Pre ) \
do_klass(Configuration_klass, java_lang_module_Configuration, Pre ) \
do_klass(ImmutableCollections_ListN_klass, java_util_ImmutableCollections_ListN, Pre ) \
do_klass(ImmutableCollections_MapN_klass, java_util_ImmutableCollections_MapN, Pre ) \
do_klass(ImmutableCollections_SetN_klass, java_util_ImmutableCollections_SetN, Pre ) \
do_klass(ArchivedModuleGraph_klass, jdk_internal_module_ArchivedModuleGraph, Pre ) \
\
do_klass(StackTraceElement_klass, java_lang_StackTraceElement, Opt ) \

View File

@ -648,13 +648,20 @@
JFR_TEMPLATES(template) \
\
/* cds */ \
template(configuration_signature, "Ljava/lang/module/Configuration;") \
template(java_lang_module_Configuration, "java/lang/module/Configuration") \
template(java_util_ImmutableCollections_ListN, "java/util/ImmutableCollections$ListN") \
template(java_util_ImmutableCollections_MapN, "java/util/ImmutableCollections$MapN") \
template(java_util_ImmutableCollections_SetN, "java/util/ImmutableCollections$SetN") \
template(jdk_internal_loader_ClassLoaders, "jdk/internal/loader/ClassLoaders") \
template(jdk_vm_cds_SharedClassInfo, "jdk/vm/cds/SharedClassInfo") \
template(url_void_signature, "(Ljava/net/URL;)V") \
template(list_signature, "Ljava/util/List;") \
template(map_signature, "Ljava/util/Map;") \
template(moduleFinder_signature, "Ljava/lang/module/ModuleFinder;") \
template(set_signature, "Ljava/util/Set;") \
template(systemModules_signature, "Ljdk/internal/module/SystemModules;") \
template(toFileURL_name, "toFileURL") \
template(toFileURL_signature, "(Ljava/lang/String;)Ljava/net/URL;") \
template(moduleFinder_signature, "Ljava/lang/module/ModuleFinder;") \
template(systemModules_signature, "Ljdk/internal/module/SystemModules;") \
template(url_void_signature, "(Ljava/net/URL;)V") \
\
/*end*/

View File

@ -104,6 +104,13 @@ void KlassSubGraphInfo::add_subgraph_object_klass(Klass* orig_k, Klass *relocate
}
assert(relocated_k->is_shared(), "must be a shared class");
if (_k == relocated_k) {
// Don't add the Klass containing the sub-graph to it's own klass
// initialization list.
return;
}
if (relocated_k->is_instance_klass()) {
assert(InstanceKlass::cast(relocated_k)->is_shared_boot_class(),
"must be boot class");
@ -498,7 +505,12 @@ void HeapShared::archive_reachable_objects_from_static_field(Klass *k,
#define do_module_object_graph(archive_object_graph_do) \
archive_object_graph_do(SystemDictionary::ArchivedModuleGraph_klass(), jdk_internal_module_ArchivedModuleGraph::archivedSystemModules_offset(), T_OBJECT, CHECK); \
archive_object_graph_do(SystemDictionary::ArchivedModuleGraph_klass(), jdk_internal_module_ArchivedModuleGraph::archivedModuleFinder_offset(), T_OBJECT, CHECK); \
archive_object_graph_do(SystemDictionary::ArchivedModuleGraph_klass(), jdk_internal_module_ArchivedModuleGraph::archivedMainModule_offset(), T_OBJECT, CHECK)
archive_object_graph_do(SystemDictionary::ArchivedModuleGraph_klass(), jdk_internal_module_ArchivedModuleGraph::archivedMainModule_offset(), T_OBJECT, CHECK); \
archive_object_graph_do(SystemDictionary::ArchivedModuleGraph_klass(), jdk_internal_module_ArchivedModuleGraph::archivedConfiguration_offset(), T_OBJECT, CHECK); \
archive_object_graph_do(SystemDictionary::ImmutableCollections_ListN_klass(), java_util_ImmutableCollections_ListN::EMPTY_LIST_offset(), T_OBJECT, CHECK); \
archive_object_graph_do(SystemDictionary::ImmutableCollections_MapN_klass(), java_util_ImmutableCollections_MapN::EMPTY_MAP_offset(), T_OBJECT, CHECK); \
archive_object_graph_do(SystemDictionary::ImmutableCollections_SetN_klass(), java_util_ImmutableCollections_SetN::EMPTY_SET_offset(), T_OBJECT, CHECK); \
archive_object_graph_do(SystemDictionary::Configuration_klass(), java_lang_module_Configuration::EMPTY_CONFIGURATION_offset(), T_OBJECT, CHECK)
void HeapShared::archive_module_graph_objects(Thread* THREAD) {
do_module_object_graph(archive_reachable_objects_from_static_field);

View File

@ -438,6 +438,7 @@ void MetaspaceShared::serialize_well_known_classes(SerializeClosure* soc) {
java_lang_Thread::serialize(soc);
java_lang_ThreadGroup::serialize(soc);
java_lang_AssertionStatusDirectives::serialize(soc);
java_lang_module_Configuration::serialize(soc);
java_lang_ref_SoftReference::serialize(soc);
java_lang_invoke_MethodHandle::serialize(soc);
java_lang_invoke_DirectMethodHandle::serialize(soc);
@ -461,6 +462,9 @@ void MetaspaceShared::serialize_well_known_classes(SerializeClosure* soc) {
java_lang_StackFrameInfo::serialize(soc);
java_lang_LiveStackFrameInfo::serialize(soc);
java_util_concurrent_locks_AbstractOwnableSynchronizer::serialize(soc);
java_util_ImmutableCollections_ListN::serialize(soc);
java_util_ImmutableCollections_MapN::serialize(soc);
java_util_ImmutableCollections_SetN::serialize(soc);
jdk_internal_module_ArchivedModuleGraph::serialize(soc);
}

View File

@ -41,8 +41,10 @@ import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import jdk.internal.misc.VM;
import jdk.internal.module.ModuleReferenceImpl;
import jdk.internal.module.ModuleTarget;
import jdk.internal.vm.annotation.Stable;
/**
* A configuration that is the result of <a href="package-summary.html#resolution">
@ -103,7 +105,17 @@ import jdk.internal.module.ModuleTarget;
public final class Configuration {
// @see Configuration#empty()
private static final Configuration EMPTY_CONFIGURATION = new Configuration();
// EMPTY_CONFIGURATION may be initialized from the CDS archive.
private static @Stable Configuration EMPTY_CONFIGURATION;
static {
// Initialize EMPTY_CONFIGURATION from the archive.
VM.initializeFromArchive(Configuration.class);
// Create a new empty Configuration if there is no archived version.
if (EMPTY_CONFIGURATION == null) {
EMPTY_CONFIGURATION = new Configuration();
}
}
// parent configurations, in search order
private final List<Configuration> parents;

View File

@ -36,6 +36,7 @@ import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.misc.VM;
import jdk.internal.vm.annotation.Stable;
/**
@ -409,7 +410,15 @@ class ImmutableCollections {
static final class ListN<E> extends AbstractImmutableList<E>
implements Serializable {
static final List<?> EMPTY_LIST = new ListN<>();
// EMPTY_LIST may be initialized from the CDS archive.
static @Stable List<?> EMPTY_LIST;
static {
VM.initializeFromArchive(ListN.class);
if (EMPTY_LIST == null) {
EMPTY_LIST = new ListN<>();
}
}
@Stable
private final E[] elements;
@ -567,7 +576,15 @@ class ImmutableCollections {
static final class SetN<E> extends AbstractImmutableSet<E>
implements Serializable {
static final Set<?> EMPTY_SET = new SetN<>();
// EMPTY_SET may be initialized from the CDS archive.
static @Stable Set<?> EMPTY_SET;
static {
VM.initializeFromArchive(SetN.class);
if (EMPTY_SET == null) {
EMPTY_SET = new SetN<>();
}
}
@Stable
final E[] elements;
@ -772,7 +789,15 @@ class ImmutableCollections {
*/
static final class MapN<K,V> extends AbstractImmutableMap<K,V> {
static final Map<?,?> EMPTY_MAP = new MapN<>();
// EMPTY_MAP may be initialized from the CDS archive.
static @Stable Map<?,?> EMPTY_MAP;
static {
VM.initializeFromArchive(MapN.class);
if (EMPTY_MAP == null) {
EMPTY_MAP = new MapN<>();
}
}
@Stable
final Object[] table; // pairs of key, value

View File

@ -25,6 +25,7 @@
package jdk.internal.module;
import java.lang.module.Configuration;
import java.lang.module.ModuleFinder;
import java.util.Objects;
import jdk.internal.misc.VM;
@ -36,13 +37,18 @@ final class ArchivedModuleGraph {
private static String archivedMainModule;
private static SystemModules archivedSystemModules;
private static ModuleFinder archivedModuleFinder;
private static Configuration archivedConfiguration;
private final SystemModules systemModules;
private final ModuleFinder finder;
private final Configuration configuration;
private ArchivedModuleGraph(SystemModules modules, ModuleFinder finder) {
private ArchivedModuleGraph(SystemModules modules,
ModuleFinder finder,
Configuration configuration) {
this.systemModules = modules;
this.finder = finder;
this.configuration = configuration;
}
SystemModules systemModules() {
@ -53,27 +59,36 @@ final class ArchivedModuleGraph {
return finder;
}
Configuration configuration() {
return configuration;
}
// A factory method that ModuleBootstrap can use to obtain the
// ArchivedModuleGraph.
static ArchivedModuleGraph get(String mainModule) {
if (Objects.equals(mainModule, archivedMainModule)
&& archivedSystemModules != null
&& archivedModuleFinder != null) {
&& archivedModuleFinder != null
&& archivedConfiguration != null) {
return new ArchivedModuleGraph(archivedSystemModules,
archivedModuleFinder);
archivedModuleFinder,
archivedConfiguration);
} else {
return null;
}
}
// Used at CDS dump time
static void archive(String mainModule, SystemModules systemModules,
ModuleFinder finder) {
static void archive(String mainModule,
SystemModules systemModules,
ModuleFinder finder,
Configuration configuration) {
if (archivedMainModule != null)
throw new UnsupportedOperationException();
archivedMainModule = mainModule;
archivedSystemModules = systemModules;
archivedModuleFinder = finder;
archivedConfiguration = configuration;
}
static {

View File

@ -172,6 +172,7 @@ public final class ModuleBootstrap {
boolean haveModulePath = (appModulePath != null || upgradeModulePath != null);
boolean needResolution = true;
boolean canArchive = false;
// If the java heap was archived at CDS dump time and the environment
// at dump time matches the current environment then use the archived
@ -186,7 +187,6 @@ public final class ModuleBootstrap {
systemModuleFinder = archivedModuleGraph.finder();
needResolution = (traceOutput != null);
} else {
boolean canArchive = false;
if (!haveModulePath && addModules.isEmpty() && limitModules.isEmpty()) {
systemModules = SystemModuleFinders.systemModules(mainModule);
if (systemModules != null && !isPatched) {
@ -206,12 +206,6 @@ public final class ModuleBootstrap {
systemModules = new ExplodedSystemModules();
systemModuleFinder = SystemModuleFinders.ofSystem();
}
// Module graph can be archived at CDS dump time. Only allow the
// unnamed module case for now.
if (canArchive && (mainModule == null)) {
ArchivedModuleGraph.archive(mainModule, systemModules, systemModuleFinder);
}
}
Counters.add("jdk.module.boot.1.systemModulesTime", t1);
@ -353,8 +347,12 @@ public final class ModuleBootstrap {
if (needResolution) {
cf = JLMA.resolveAndBind(finder, roots, traceOutput);
} else {
Map<String, Set<String>> map = systemModules.moduleReads();
cf = JLMA.newConfiguration(systemModuleFinder, map);
if (archivedModuleGraph != null) {
cf = archivedModuleGraph.configuration();
} else {
Map<String, Set<String>> map = systemModules.moduleReads();
cf = JLMA.newConfiguration(systemModuleFinder, map);
}
}
// check that modules specified to --patch-module are resolved
@ -436,6 +434,13 @@ public final class ModuleBootstrap {
limitedFinder = new SafeModuleFinder(finder);
}
// Module graph can be archived at CDS dump time. Only allow the
// unnamed module case for now.
if (canArchive && (mainModule == null)) {
ArchivedModuleGraph.archive(mainModule, systemModules,
systemModuleFinder, cf);
}
// total time to initialize
Counters.add("jdk.module.boot.totalTime", t0);
Counters.publish();

View File

@ -54,41 +54,49 @@ public class ArchivedModuleComboTest {
Path userDir = Paths.get(System.getProperty("user.dir"));
Path moduleDir = Files.createTempDirectory(userDir, "mods");
// Dump without --module-path
//
// Dump without --module-path, without --show-module-resolution
//
OutputAnalyzer output = TestCommon.dump(appJar,
TestCommon.list("CheckArchivedModuleApp"),
use_whitebox_jar);
TestCommon.checkDump(output);
// Test case 1)
// - Dump without --module-path
// - Run from -cp only, archived boot layer module ModuleDescriptors
// should be used.
// - Dump without --module-path, without --show-module-resolution
// - Run from -cp only and without --show-module-resolution
// + archived boot layer module ModuleDescriptors should be used
// + archived boot layer configuration should be used
System.out.println("----------------------- Test case 1 ----------------------");
output = TestCommon.exec(appJar, use_whitebox_jar,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"CheckArchivedModuleApp",
"yes",
"yes");
TestCommon.checkExec(output);
// Test case 2)
// - Dump without --module-path
// - Run from -cp only, archived boot layer module ModuleDescriptors
// should be used with --show-module-resolution (requires resolution).
// - Dump without --module-path, without --show-module-resolution
// - Run from -cp only and with --show-module-resolution
// + archived boot layer module ModuleDescriptors should be used with
// --show-module-resolution (requires resolution)
// + archived boot layer Configuration should not be disabled
System.out.println("----------------------- Test case 2 ----------------------");
output = TestCommon.exec(appJar, use_whitebox_jar,
"--show-module-resolution",
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"CheckArchivedModuleApp",
"yes");
TestCommon.checkExec(output);
"yes",
"no");
TestCommon.checkExec(output, "root java.base jrt:/java.base");
// Test case 3)
// - Dump without --module-path
// - Run with --module-path, archived boot layer module ModuleDescriptors
// should be disabled.
// - Dump without --module-path, without --show-module-resolution
// - Run with --module-path
// + archived boot layer module ModuleDescriptors should be disabled
// + archived boot layer Configuration should be disabled
System.out.println("----------------------- Test case 3 ----------------------");
output = TestCommon.exec(appJar, use_whitebox_jar,
"--module-path",
@ -96,12 +104,15 @@ public class ArchivedModuleComboTest {
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"CheckArchivedModuleApp",
"no",
"no");
TestCommon.checkExec(output);
//
// Dump with --module-path specified (test case 4, 5). Use an
// empty directory as it's simple and still triggers the case
// where system module objects are not archived.
//
output = TestCommon.dump(appJar,
TestCommon.list("CheckArchivedModuleApp"),
"--module-path",
@ -112,19 +123,20 @@ public class ArchivedModuleComboTest {
// Test case 4)
// - Dump with --module-path
// - Run from -cp only, no archived boot layer module ModuleDescriptors
// should be found.
// and Configuration should be found.
System.out.println("----------------------- Test case 4 ----------------------");
output = TestCommon.exec(appJar, use_whitebox_jar,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"CheckArchivedModuleApp",
"no",
"no");
TestCommon.checkExec(output);
// Test case 5)
// - Dump with --module-path
// - Run with --module-path, no archived boot layer module ModuleDescriptors
// should be found.
// and Configuration should be found.
System.out.println("----------------------- Test case 5 ----------------------");
output = TestCommon.exec(appJar, use_whitebox_jar,
"--module-path",
@ -132,7 +144,47 @@ public class ArchivedModuleComboTest {
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"CheckArchivedModuleApp",
"no",
"no");
TestCommon.checkExec(output);
//
// Dump without --module-path, with --show-module-resolution
//
output = TestCommon.dump(appJar,
TestCommon.list("CheckArchivedModuleApp"),
"--show-module-resolution",
use_whitebox_jar);
TestCommon.checkDump(output, "root java.base jrt:/java.base");
// Test case 6)
// - Dump without --module-path, with --show-module-resolution
// - Run from -cp only and without --show-module-resolution
// + archived boot layer module ModuleDescriptors should be used
// + archived boot layer Configuration should be used
System.out.println("----------------------- Test case 6 ----------------------");
output = TestCommon.exec(appJar, use_whitebox_jar,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"CheckArchivedModuleApp",
"yes",
"yes");
TestCommon.checkExec(output);
// Test case 7)
// - Dump without --module-path, with --show-module-resolution
// - Run from -cp only and with --show-module-resolution
// + archived boot layer module ModuleDescriptors should be used with
// --show-module-resolution (requires resolution)
// + archived boot layer Configuration should be disabled
System.out.println("----------------------- Test case 7 ----------------------");
output = TestCommon.exec(appJar, use_whitebox_jar,
"--show-module-resolution",
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"CheckArchivedModuleApp",
"yes",
"no");
TestCommon.checkExec(output, "root java.base jrt:/java.base");
}
}

View File

@ -130,6 +130,7 @@ public class ArchivedModuleWithCustomImageTest {
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"CheckArchivedModuleApp",
"yes",
"yes"};
printCommand(runCmd);
ProcessBuilder pbRun = new ProcessBuilder();

View File

@ -23,7 +23,9 @@
*/
import java.io.File;
import java.lang.module.Configuration;
import java.lang.module.ModuleDescriptor;
import java.util.List;
import java.util.Set;
import sun.hotspot.WhiteBox;
@ -41,16 +43,23 @@ public class CheckArchivedModuleApp {
return;
}
boolean expectArchived = "yes".equals(args[0]);
checkModuleDescriptors(expectArchived);
if (args.length != 2) {
throw new RuntimeException(
"FAILED. Incorrect argument length: " + args.length);
}
boolean expectArchivedDescriptors = "yes".equals(args[0]);
boolean expectArchivedConfiguration = "yes".equals(args[1]);
checkModuleDescriptors(expectArchivedDescriptors);
checkConfiguration(expectArchivedConfiguration);
checkEmptyConfiguration(expectArchivedConfiguration);
}
private static void checkModuleDescriptors(boolean expectArchived) {
private static void checkModuleDescriptors(boolean expectArchivedDescriptors) {
Set<Module> modules = ModuleLayer.boot().modules();
for (Module m : modules) {
ModuleDescriptor md = m.getDescriptor();
String name = md.name();
if (expectArchived) {
if (expectArchivedDescriptors) {
if (wb.isShared(md)) {
System.out.println(name + " is archived. Expected.");
} else {
@ -67,4 +76,58 @@ public class CheckArchivedModuleApp {
}
}
}
private static void checkEmptyConfiguration(boolean expectArchivedConfiguration) {
// Configuration.EMPTY_CONFIGURATION uses the singletons,
// ListN.EMPTY_LIST, SetN.EMPTY_SET and MapN.EMPTY_MAP in
// ImmutableCollections for the 'parents', 'modules' and
// 'graph' fields. The ImmutableCollections singletons
// can be accessed via List.of(), Set.of() and Map.of() APIs.
// Configuration public APIs also allow access to the
// EMPTY_CONFIGURATION's 'parents' and 'modules'. When the
// archived java heap data is enabled at runtime, make sure
// the EMPTY_CONFIGURATION.parents and EMPTY_CONFIGURATION.modules
// are the archived ImmutableCollections singletons.
Configuration emptyCf = Configuration.empty();
List emptyCfParents = emptyCf.parents();
Set emptyCfModules = emptyCf.modules();
if (expectArchivedConfiguration) {
if (emptyCfParents == List.of() &&
wb.isShared(emptyCfParents)) {
System.out.println("Empty Configuration has expected parents.");
} else {
throw new RuntimeException(
"FAILED. Unexpected parents for empty Configuration.");
}
if (emptyCfModules == Set.of() &&
wb.isShared(emptyCfModules)) {
System.out.println("Empty Configuration has expected module set.");
} else {
throw new RuntimeException(
"FAILED. Unexpected module set for empty Configuration.");
}
}
}
private static void checkConfiguration(boolean expectArchivedConfiguration) {
Configuration cf = ModuleLayer.boot().configuration();
if (expectArchivedConfiguration) {
if (wb.isShared(cf)) {
System.out.println("Boot layer configuration is archived. Expected.");
} else {
throw new RuntimeException(
"FAILED. Boot layer configuration is not archived.");
}
} else {
if (!wb.isShared(cf)) {
System.out.println("Boot layer configuration is not archived. Expected.");
} else {
throw new RuntimeException(
"FAILED. Boot layer configuration is archived.");
}
}
}
}