Skip to content

Commit 58736f7

Browse files
Updates and test fixing.
* Fix test for new ModuleReference behaviour. * Make preview mode system property dependent in classloader. * Update benchmark for preview mode and new ImageReader methods.
1 parent ee3dbcf commit 58736f7

File tree

5 files changed

+1148
-989
lines changed

5 files changed

+1148
-989
lines changed

src/hotspot/share/runtime/arguments.cpp

Lines changed: 50 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2079,56 +2079,69 @@ int Arguments::process_patch_mod_option(const char* patch_mod_tail) {
20792079
return JNI_OK;
20802080
}
20812081

2082+
// Temporary system property to disable preview patching and enable the new preview mode
2083+
// feature for testing/development. Once the preview mode feature is finished, the value
2084+
// will be always 'true' and this code, and all related dead-code can be removed.
2085+
#define DISABLE_PREVIEW_PATCHING_DEFAULT false
2086+
2087+
bool Arguments::disable_preview_patching() {
2088+
const char* prop = get_property("DISABLE_PREVIEW_PATCHING");
2089+
return (prop != nullptr)
2090+
? strncmp(prop, "true", strlen("true")) == 0
2091+
: DISABLE_PREVIEW_PATCHING_DEFAULT;
2092+
}
2093+
20822094
// VALUECLASS_STR must match string used in the build
20832095
#define VALUECLASS_STR "valueclasses"
20842096
#define VALUECLASS_JAR "-" VALUECLASS_STR ".jar"
20852097

20862098
// Finalize --patch-module args and --enable-preview related to value class module patches.
20872099
// Create all numbered properties passing module patches.
20882100
int Arguments::finalize_patch_module() {
2089-
// If --enable-preview and EnableValhalla is true, each module may have value classes that
2090-
// are to be patched into the module.
2101+
// If --enable-preview and EnableValhalla is true, modules may have preview mode resources.
20912102
bool enable_valhalla_preview = enable_preview() && EnableValhalla;
2103+
// Whether to use module patching, or the new preview mode feature for preview resources.
2104+
bool disable_patching = disable_preview_patching();
20922105

20932106
// This must be called, even with 'false', to enable resource lookup from JImage.
2094-
ClassLoader::init_jimage(enable_valhalla_preview);
2107+
ClassLoader::init_jimage(disable_patching && enable_valhalla_preview);
2108+
2109+
// For each <module>-valueclasses.jar in <JAVA_HOME>/lib/valueclasses/
2110+
// appends the equivalent of --patch-module <module>=<JAVA_HOME>/lib/valueclasses/<module>-valueclasses.jar
2111+
if (!disable_patching && enable_valhalla_preview) {
2112+
char * valueclasses_dir = AllocateHeap(JVM_MAXPATHLEN, mtArguments);
2113+
const char * fileSep = os::file_separator();
2114+
2115+
jio_snprintf(valueclasses_dir, JVM_MAXPATHLEN, "%s%slib%s" VALUECLASS_STR "%s",
2116+
Arguments::get_java_home(), fileSep, fileSep, fileSep);
2117+
DIR* dir = os::opendir(valueclasses_dir);
2118+
if (dir != nullptr) {
2119+
char * module_name = AllocateHeap(JVM_MAXPATHLEN, mtArguments);
2120+
char * path = AllocateHeap(JVM_MAXPATHLEN, mtArguments);
2121+
2122+
for (dirent * entry = os::readdir(dir); entry != nullptr; entry = os::readdir(dir)) {
2123+
// Test if file ends-with "-valueclasses.jar"
2124+
int len = (int)strlen(entry->d_name) - (sizeof(VALUECLASS_JAR) - 1);
2125+
if (len <= 0 || strcmp(&entry->d_name[len], VALUECLASS_JAR) != 0) {
2126+
continue; // too short or not the expected suffix
2127+
}
20952128

2096-
// // For each <module>-valueclasses.jar in <JAVA_HOME>/lib/valueclasses/
2097-
// // appends the equivalent of --patch-module <module>=<JAVA_HOME>/lib/valueclasses/<module>-valueclasses.jar
2098-
// if (enable_valhalla_preview) {
2099-
// char * valueclasses_dir = AllocateHeap(JVM_MAXPATHLEN, mtArguments);
2100-
// const char * fileSep = os::file_separator();
2101-
//
2102-
// jio_snprintf(valueclasses_dir, JVM_MAXPATHLEN, "%s%slib%s" VALUECLASS_STR "%s",
2103-
// Arguments::get_java_home(), fileSep, fileSep, fileSep);
2104-
// DIR* dir = os::opendir(valueclasses_dir);
2105-
// if (dir != nullptr) {
2106-
// char * module_name = AllocateHeap(JVM_MAXPATHLEN, mtArguments);
2107-
// char * path = AllocateHeap(JVM_MAXPATHLEN, mtArguments);
2108-
//
2109-
// for (dirent * entry = os::readdir(dir); entry != nullptr; entry = os::readdir(dir)) {
2110-
// // Test if file ends-with "-valueclasses.jar"
2111-
// int len = (int)strlen(entry->d_name) - (sizeof(VALUECLASS_JAR) - 1);
2112-
// if (len <= 0 || strcmp(&entry->d_name[len], VALUECLASS_JAR) != 0) {
2113-
// continue; // too short or not the expected suffix
2114-
// }
2115-
//
2116-
// strcpy(module_name, entry->d_name);
2117-
// module_name[len] = '\0'; // truncate to just module-name
2118-
//
2119-
// jio_snprintf(path, JVM_MAXPATHLEN, "%s%s", valueclasses_dir, &entry->d_name);
2120-
// add_patch_mod_prefix(module_name, path, true /* append */, true /* cds OK*/);
2121-
// log_info(class)("--enable-preview appending value classes for module %s: %s", module_name, entry->d_name);
2122-
// }
2123-
// FreeHeap(module_name);
2124-
// FreeHeap(path);
2125-
// os::closedir(dir);
2126-
// }
2127-
// FreeHeap(valueclasses_dir);
2128-
// }
2129+
strcpy(module_name, entry->d_name);
2130+
module_name[len] = '\0'; // truncate to just module-name
2131+
2132+
jio_snprintf(path, JVM_MAXPATHLEN, "%s%s", valueclasses_dir, &entry->d_name);
2133+
add_patch_mod_prefix(module_name, path, true /* append */, true /* cds OK*/);
2134+
log_info(class)("--enable-preview appending value classes for module %s: %s", module_name, entry->d_name);
2135+
}
2136+
FreeHeap(module_name);
2137+
FreeHeap(path);
2138+
os::closedir(dir);
2139+
}
2140+
FreeHeap(valueclasses_dir);
2141+
}
21292142

21302143
// Create numbered properties for each module that has been patched either
2131-
// by --patch-module or --enable-preview
2144+
// by --patch-module (or --enable-preview if disable_patching is false).
21322145
// Format is "jdk.module.patch.<n>=<module_name>=<path>"
21332146
if (_patch_mod_prefix != nullptr) {
21342147
char * prop_value = AllocateHeap(JVM_MAXPATHLEN + JVM_MAXPATHLEN + 1, mtArguments);

src/hotspot/share/runtime/arguments.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,8 @@ class Arguments : AllStatic {
486486
// Set up the underlying pieces of the boot class path
487487
static void add_patch_mod_prefix(const char *module_name, const char *path, bool allow_append, bool allow_cds);
488488
static int finalize_patch_module();
489+
static bool disable_preview_patching();
490+
489491
static void set_boot_class_path(const char *value, bool has_jimage) {
490492
// During start up, set by os::set_boot_path()
491493
assert(get_boot_class_path() == nullptr, "Boot class path previously set");

src/java.base/share/classes/jdk/internal/jimage/ModuleReference.java

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -222,30 +222,44 @@ public Integer next() {
222222
}
223223

224224
/**
225-
* Writes a list of module references to a given buffer.
225+
* Writes a list of module references to a given buffer. The given references
226+
* list is checked carefully to ensure the written buffer will be valid.
226227
*
227228
* <p>Entries are written in order, taking two integer slots per entry as
228229
* {@code [<flags>, <encoded-name>]}.
229230
*
230231
* @param refs the references to write, correctly ordered.
231232
* @param buffer destination buffer.
232233
* @param nameEncoder encoder for module names.
234+
* @throws IllegalArgumentException in the references are invalid in any way.
233235
*/
234236
public static void write(
235237
List<ModuleReference> refs, IntBuffer buffer, Function<String, Integer> nameEncoder) {
236-
if (buffer.capacity() != (2 * refs.size())) {
237-
throw new IllegalArgumentException("Incorrect output buffer capacity");
238+
if (refs.isEmpty()) {
239+
throw new IllegalArgumentException("References list must be non-empty");
238240
}
239-
int withContent = 0;
240-
for (ModuleReference modRef : refs) {
241-
if (modRef.hasContent()) {
242-
withContent++;
241+
int expectedCapacity = 2 * refs.size();
242+
if (buffer.capacity() != expectedCapacity) {
243+
throw new IllegalArgumentException(
244+
"Invalid buffer capacity: expected " + expectedCapacity + ", got " + buffer.capacity());
245+
}
246+
// This catches exact duplicates in the list.
247+
refs.stream().reduce((lhs, rhs) -> {
248+
if (lhs.compareTo(rhs) >= 0) {
249+
throw new IllegalArgumentException("References must be strictly ordered: " + refs);
243250
}
244-
buffer.put(modRef.flags);
245-
buffer.put(nameEncoder.apply(modRef.name));
251+
return rhs;
252+
});
253+
// Distinct references can have the same name (but we don't allow this).
254+
if (refs.stream().map(ModuleReference::name).distinct().count() != refs.size()) {
255+
throw new IllegalArgumentException("Reference names must be unique: " + refs);
246256
}
247-
if (withContent > 1) {
257+
if (refs.stream().filter(ModuleReference::hasContent).count() > 1) {
248258
throw new IllegalArgumentException("At most one reference can have content: " + refs);
249259
}
260+
for (ModuleReference modRef : refs) {
261+
buffer.put(modRef.flags);
262+
buffer.put(nameEncoder.apply(modRef.name));
263+
}
250264
}
251265
}

0 commit comments

Comments
 (0)