Skip to content

Commit e0d7959

Browse files
Rollup commit after sync.
* Reenable validation * Undoing debug stuff. * Fix daft preview flag mistake. * [[AUTOMATIC FORMATTING]] * WIP - push for Roger. * Builds to completion for "make images" but value tests don't run. * Fix build issue with copied files. * Automatic Java reformat * Work in progress - builds but no tests yet. * Tidying up inconsistencies. * More encapsulation of JImage_file and mode into private static functions. Now the preview flag is plumbed into the JImage code, but not acted upon yet. * Change method return back to base class type (nobody relies on the sub-type). * Isolate JImage use within ClassPathImageEntry.
1 parent b5395e8 commit e0d7959

File tree

15 files changed

+342
-187
lines changed

15 files changed

+342
-187
lines changed

make/CompileJavaModules.gmk

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,16 @@ endif
9999

100100
################################################################################
101101
# Setup the main compilation
102+
103+
COMPILATION_OUTPUTDIR := $(if $($(MODULE)_BIN), $($(MODULE)_BIN), $(JDK_OUTPUTDIR)/modules)
104+
102105
$(eval $(call SetupJavaCompilation, $(MODULE), \
103106
SMALL_JAVA := false, \
104107
MODULE := $(MODULE), \
105108
SRC := $(wildcard $(MODULE_SRC_DIRS)), \
106109
INCLUDES := $(JDK_USER_DEFINED_FILTER), \
107110
FAIL_NO_SRC := $(FAIL_NO_SRC), \
108-
BIN := $(if $($(MODULE)_BIN), $($(MODULE)_BIN), $(JDK_OUTPUTDIR)/modules), \
111+
BIN := $(COMPILATION_OUTPUTDIR), \
109112
HEADERS := $(SUPPORT_OUTPUTDIR)/headers, \
110113
CREATE_API_DIGEST := true, \
111114
CLEAN := $(CLEAN), \
@@ -136,14 +139,23 @@ ifneq ($(COMPILER), bootjdk)
136139
MODULE_VALUECLASS_SRC_DIRS := $(call FindModuleValueClassSrcDirs, $(MODULE))
137140
MODULE_VALUECLASS_SOURCEPATH := $(call GetModuleValueClassSrcPath)
138141

142+
# Temporarily compile valueclasses into a separate directory with the form:
143+
# <tempdir>/<module>/<classpath>
144+
# and then copy the class files into:
145+
# <outdir>/<module>/META-INF/preview/<classpath>
146+
# We cannot compile directly into the desired directory because it's the
147+
# compiler which creates the original '<module>/<classpath>/...' hierarchy.
148+
VALUECLASS_OUTPUTDIR := $(SUPPORT_OUTPUTDIR)/$(VALUECLASSES_STR)
149+
PREVIEW_OUTPUTDIR := $(COMPILATION_OUTPUTDIR)/$(MODULE)/META-INF/preview
150+
139151
ifneq ($(MODULE_VALUECLASS_SRC_DIRS),)
140152
$(eval $(call SetupJavaCompilation, $(MODULE)-$(VALUECLASSES_STR), \
141153
SMALL_JAVA := false, \
142154
MODULE := $(MODULE), \
143155
SRC := $(wildcard $(MODULE_VALUECLASS_SRC_DIRS)), \
144156
INCLUDES := $(JDK_USER_DEFINED_FILTER), \
145157
FAIL_NO_SRC := $(FAIL_NO_SRC), \
146-
BIN := $(SUPPORT_OUTPUTDIR)/$(VALUECLASSES_STR)/, \
158+
BIN := $(VALUECLASS_OUTPUTDIR), \
147159
JAR := $(JDK_OUTPUTDIR)/lib/$(VALUECLASSES_STR)/$(MODULE)-$(VALUECLASSES_STR).jar, \
148160
HEADERS := $(SUPPORT_OUTPUTDIR)/headers, \
149161
DISABLED_WARNINGS := $(DISABLED_WARNINGS_java) preview, \
@@ -161,6 +173,14 @@ ifneq ($(COMPILER), bootjdk)
161173

162174
TARGETS += $($(MODULE)-$(VALUECLASSES_STR))
163175

176+
# Restructure the class file hierarchy from <module>/<classpath>/... to <module>/META-INF/preview/<classpath>/...
177+
$(PREVIEW_OUTPUTDIR)/_copy_valueclasses.marker: $($(MODULE)-$(VALUECLASSES_STR))
178+
$(call MakeTargetDir)
179+
$(CP) -R $(VALUECLASS_OUTPUTDIR)/$(MODULE)/. $(@D)/
180+
$(TOUCH) $@
181+
182+
TARGETS += $(PREVIEW_OUTPUTDIR)/_copy_valueclasses.marker
183+
164184
$(eval $(call SetupCopyFiles, $(MODULE)-copy-valueclass-jar, \
165185
FILES := $(JDK_OUTPUTDIR)/lib/$(VALUECLASSES_STR)/$(MODULE)-$(VALUECLASSES_STR).jar, \
166186
DEST := $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE)/$(VALUECLASSES_STR), \

src/hotspot/share/classfile/classLoader.cpp

Lines changed: 117 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,18 @@ static JImageClose_t JImageClose = nullptr;
9797
static JImageFindResource_t JImageFindResource = nullptr;
9898
static JImageGetResource_t JImageGetResource = nullptr;
9999

100-
// JimageFile pointer, or null if exploded JDK build.
100+
// JImageFile pointer, or null if exploded JDK build.
101101
static JImageFile* JImage_file = nullptr;
102102

103+
// JImageMode status to control preview behaviour. JImage_file is unusable
104+
// for normal lookup until (JImage_mode != JIMAGE_MODE_UNINITIALIZED).
105+
enum JImageMode {
106+
JIMAGE_MODE_UNINITIALIZED = 0,
107+
JIMAGE_MODE_DEFAULT = 1,
108+
JIMAGE_MODE_ENABLE_PREVIEW = 2
109+
};
110+
static JImageMode JImage_mode = JIMAGE_MODE_UNINITIALIZED;
111+
103112
// Globals
104113

105114
PerfCounter* ClassLoader::_perf_accumulated_time = nullptr;
@@ -154,7 +163,7 @@ void ClassLoader::print_counters(outputStream *st) {
154163

155164
GrowableArray<ModuleClassPathList*>* ClassLoader::_patch_mod_entries = nullptr;
156165
GrowableArray<ModuleClassPathList*>* ClassLoader::_exploded_entries = nullptr;
157-
ClassPathEntry* ClassLoader::_jrt_entry = nullptr;
166+
ClassPathImageEntry* ClassLoader::_jrt_entry = nullptr;
158167

159168
ClassPathEntry* volatile ClassLoader::_first_append_entry_list = nullptr;
160169
ClassPathEntry* volatile ClassLoader::_last_append_entry = nullptr;
@@ -234,6 +243,74 @@ Symbol* ClassLoader::package_from_class_name(const Symbol* name, bool* bad_class
234243
return SymbolTable::new_symbol(name, pointer_delta_as_int(start, base), pointer_delta_as_int(end, base));
235244
}
236245

246+
// --------------------------------
247+
// The following jimage_xxx static functions encapsulate all JImage_file and JImage_mode access.
248+
// This is done to make it easy to reason about the JImage file state (exists vs initialized etc.).
249+
250+
// Opens the named JImage file and sets the JImage file reference.
251+
// Returns true if opening the JImage file was successful (see also jimage_exists()).
252+
static bool jimage_open(const char* modules_path) {
253+
// Currently 'error' is not set to anything useful, so ignore it here.
254+
jint error;
255+
JImage_file = (*JImageOpen)(modules_path, &error);
256+
return JImage_file != nullptr;
257+
}
258+
259+
// Closes and clears the JImage file reference (this will only be called during shutdown).
260+
static void jimage_close() {
261+
if (JImage_file != nullptr) {
262+
(*JImageClose)(JImage_file);
263+
JImage_file = nullptr;
264+
}
265+
}
266+
267+
// Returns whether a JImage file was opened (but NOT whether it was initialized yet).
268+
static bool jimage_exists() {
269+
return JImage_file != nullptr;
270+
}
271+
272+
// Returns the JImage file reference (which may or may not be initialized).
273+
static JImageFile* jimage_non_null() {
274+
assert(jimage_exists(), "should have been opened by ClassLoader::lookup_vm_options "
275+
"and remained throughout normal JVM lifetime");
276+
return JImage_file;
277+
}
278+
279+
// Called once to set the access mode for resource (i.e. preview or non-preview) before
280+
// general resource lookup can occur.
281+
static void jimage_init(bool enable_preview) {
282+
assert(JImage_mode == JIMAGE_MODE_UNINITIALIZED, "jimage_init must not be called twice");
283+
JImage_mode = enable_preview ? JIMAGE_MODE_ENABLE_PREVIEW : JIMAGE_MODE_DEFAULT;
284+
}
285+
286+
// Returns true if jimage_init() has been called. Once the JImage file is initialized,
287+
// jimage_is_preview_enabled() can be called to correctly determine the access mode.
288+
static bool jimage_is_initialized() {
289+
return jimage_exists() && JImage_mode != JIMAGE_MODE_UNINITIALIZED;
290+
}
291+
292+
// Returns the access mode for an initialized JImage file (reflects --enable-preview).
293+
static bool jimage_is_preview_enabled() {
294+
assert(jimage_is_initialized(), "jimage is not initialized");
295+
return JImage_mode == JIMAGE_MODE_ENABLE_PREVIEW;
296+
}
297+
298+
// Looks up the location of a named JImage resource. This "raw" lookup function allows
299+
// the preview mode to be manually specified, so must not be accessible outside this
300+
// class. ClassPathImageEntry manages all calls for resources after startup is complete.
301+
static JImageLocationRef jimage_find_resource(const char* module_name,
302+
const char* file_name,
303+
bool is_preview,
304+
jlong *size) {
305+
return ((*JImageFindResource)(jimage_non_null(),
306+
module_name,
307+
get_jimage_version_string(),
308+
file_name,
309+
is_preview,
310+
size));
311+
}
312+
// --------------------------------
313+
237314
// Given a fully qualified package name, find its defining package in the class loader's
238315
// package entry table.
239316
PackageEntry* ClassLoader::get_package_entry(Symbol* pkg_name, ClassLoaderData* loader_data) {
@@ -358,28 +435,15 @@ ClassFileStream* ClassPathZipEntry::open_stream(JavaThread* current, const char*
358435

359436
DEBUG_ONLY(ClassPathImageEntry* ClassPathImageEntry::_singleton = nullptr;)
360437

361-
JImageFile* ClassPathImageEntry::jimage() const {
362-
return JImage_file;
363-
}
364-
365-
JImageFile* ClassPathImageEntry::jimage_non_null() const {
366-
assert(ClassLoader::has_jrt_entry(), "must be");
367-
assert(jimage() != nullptr, "should have been opened by ClassLoader::lookup_vm_options "
368-
"and remained throughout normal JVM lifetime");
369-
return jimage();
370-
}
371-
372438
void ClassPathImageEntry::close_jimage() {
373-
if (jimage() != nullptr) {
374-
(*JImageClose)(jimage());
375-
JImage_file = nullptr;
376-
}
439+
jimage_close();
377440
}
378441

379-
ClassPathImageEntry::ClassPathImageEntry(JImageFile* jimage, const char* name) :
442+
ClassPathImageEntry::ClassPathImageEntry(const char* name) :
380443
ClassPathEntry() {
381-
guarantee(jimage != nullptr, "jimage file is null");
444+
guarantee(jimage_is_initialized(), "jimage is not initialized");
382445
guarantee(name != nullptr, "jimage file name is null");
446+
383447
assert(_singleton == nullptr, "VM supports only one jimage");
384448
DEBUG_ONLY(_singleton = this);
385449
size_t len = strlen(name) + 1;
@@ -398,16 +462,18 @@ ClassFileStream* ClassPathImageEntry::open_stream(JavaThread* current, const cha
398462
// 2. A package is in at most one module in the jimage file.
399463
//
400464
ClassFileStream* ClassPathImageEntry::open_stream_for_loader(JavaThread* current, const char* name, ClassLoaderData* loader_data) {
465+
bool is_preview = jimage_is_preview_enabled();
466+
401467
jlong size;
402-
JImageLocationRef location = (*JImageFindResource)(jimage_non_null(), "", get_jimage_version_string(), name, &size);
468+
JImageLocationRef location = jimage_find_resource("", name, is_preview, &size);
403469

404470
if (location == 0) {
405471
TempNewSymbol class_name = SymbolTable::new_symbol(name);
406472
TempNewSymbol pkg_name = ClassLoader::package_from_class_name(class_name);
407473

408474
if (pkg_name != nullptr) {
409475
if (!Universe::is_module_initialized()) {
410-
location = (*JImageFindResource)(jimage_non_null(), JAVA_BASE_NAME, get_jimage_version_string(), name, &size);
476+
location = jimage_find_resource(JAVA_BASE_NAME, name, is_preview, &size);
411477
} else {
412478
PackageEntry* package_entry = ClassLoader::get_package_entry(pkg_name, loader_data);
413479
if (package_entry != nullptr) {
@@ -418,7 +484,7 @@ ClassFileStream* ClassPathImageEntry::open_stream_for_loader(JavaThread* current
418484
assert(module->is_named(), "Boot classLoader package is in unnamed module");
419485
const char* module_name = module->name()->as_C_string();
420486
if (module_name != nullptr) {
421-
location = (*JImageFindResource)(jimage_non_null(), module_name, get_jimage_version_string(), name, &size);
487+
location = jimage_find_resource(module_name, name, is_preview, &size);
422488
}
423489
}
424490
}
@@ -431,7 +497,7 @@ ClassFileStream* ClassPathImageEntry::open_stream_for_loader(JavaThread* current
431497
char* data = NEW_RESOURCE_ARRAY(char, size);
432498
(*JImageGetResource)(jimage_non_null(), location, data, size);
433499
// Resource allocated
434-
assert(this == (ClassPathImageEntry*)ClassLoader::get_jrt_entry(), "must be");
500+
assert(this == ClassLoader::get_jrt_entry(), "must be");
435501
return new ClassFileStream((u1*)data,
436502
checked_cast<int>(size),
437503
_name,
@@ -441,16 +507,9 @@ ClassFileStream* ClassPathImageEntry::open_stream_for_loader(JavaThread* current
441507
return nullptr;
442508
}
443509

444-
JImageLocationRef ClassLoader::jimage_find_resource(JImageFile* jf,
445-
const char* module_name,
446-
const char* file_name,
447-
jlong &size) {
448-
return ((*JImageFindResource)(jf, module_name, get_jimage_version_string(), file_name, &size));
449-
}
450-
451510
bool ClassPathImageEntry::is_modules_image() const {
452511
assert(this == _singleton, "VM supports a single jimage");
453-
assert(this == (ClassPathImageEntry*)ClassLoader::get_jrt_entry(), "must be used for jrt entry");
512+
assert(this == ClassLoader::get_jrt_entry(), "must be used for jrt entry");
454513
return true;
455514
}
456515

@@ -605,14 +664,15 @@ void ClassLoader::setup_bootstrap_search_path_impl(JavaThread* current, const ch
605664
struct stat st;
606665
if (os::stat(path, &st) == 0) {
607666
// Directory found
608-
if (JImage_file != nullptr) {
667+
if (jimage_exists()) {
609668
assert(Arguments::has_jimage(), "sanity check");
610669
const char* canonical_path = get_canonical_path(path, current);
611670
assert(canonical_path != nullptr, "canonical_path issue");
612671

613-
_jrt_entry = new ClassPathImageEntry(JImage_file, canonical_path);
672+
// Hand over lifecycle control of the JImage file to the _jrt_entry singleton
673+
// (see ClassPathImageEntry::close_jimage). The image must be initialized by now.
674+
_jrt_entry = new ClassPathImageEntry(canonical_path);
614675
assert(_jrt_entry != nullptr && _jrt_entry->is_modules_image(), "No java runtime image present");
615-
assert(_jrt_entry->jimage() != nullptr, "No java runtime image");
616676
} // else it's an exploded build.
617677
} else {
618678
// If path does not exist, exit
@@ -1384,49 +1444,51 @@ void ClassLoader::initialize(TRAPS) {
13841444
setup_bootstrap_search_path(THREAD);
13851445
}
13861446

1387-
static char* lookup_vm_resource(JImageFile *jimage, const char *jimage_version, const char *path) {
1388-
jlong size;
1389-
JImageLocationRef location = (*JImageFindResource)(jimage, "java.base", jimage_version, path, &size);
1390-
if (location == 0)
1391-
return nullptr;
1392-
char *val = NEW_C_HEAP_ARRAY(char, size+1, mtClass);
1393-
(*JImageGetResource)(jimage, location, val, size);
1394-
val[size] = '\0';
1395-
return val;
1396-
}
1397-
13981447
// Lookup VM options embedded in the modules jimage file
13991448
char* ClassLoader::lookup_vm_options() {
1400-
jint error;
14011449
char modules_path[JVM_MAXPATHLEN];
14021450
const char* fileSep = os::file_separator();
14031451

14041452
// Initialize jimage library entry points
14051453
load_jimage_library();
14061454

14071455
jio_snprintf(modules_path, JVM_MAXPATHLEN, "%s%slib%smodules", Arguments::get_java_home(), fileSep, fileSep);
1408-
JImage_file =(*JImageOpen)(modules_path, &error);
1409-
if (JImage_file == nullptr) {
1410-
return nullptr;
1456+
if (jimage_open(modules_path)) {
1457+
// Special case where we lookup the options string *before* calling jimage_init().
1458+
// Since VM arguments have not been parsed, and the ClassPathImageEntry singleton
1459+
// has not been created yet, we access the JImage file directly in non-preview mode.
1460+
jlong size;
1461+
JImageLocationRef location =
1462+
jimage_find_resource(JAVA_BASE_NAME, "jdk/internal/vm/options", /* is_preview */ false, &size);
1463+
if (location != 0) {
1464+
char *options = NEW_C_HEAP_ARRAY(char, size+1, mtClass);
1465+
(*JImageGetResource)(jimage_non_null(), location, options, size);
1466+
options[size] = '\0';
1467+
return options;
1468+
}
14111469
}
1470+
return nullptr;
1471+
}
14121472

1413-
const char *jimage_version = get_jimage_version_string();
1414-
char *options = lookup_vm_resource(JImage_file, jimage_version, "jdk/internal/vm/options");
1415-
return options;
1473+
// Finishes initializing the JImageFile (if present) by setting the access mode.
1474+
void ClassLoader::init_jimage(bool enable_preview) {
1475+
if (jimage_exists()) {
1476+
jimage_init(enable_preview);
1477+
}
14161478
}
14171479

14181480
bool ClassLoader::is_module_observable(const char* module_name) {
14191481
assert(JImageOpen != nullptr, "jimage library should have been opened");
1420-
if (JImage_file == nullptr) {
1482+
if (!jimage_exists()) {
14211483
struct stat st;
14221484
const char *path = get_exploded_module_path(module_name, true);
14231485
bool res = os::stat(path, &st) == 0;
14241486
FREE_C_HEAP_ARRAY(char, path);
14251487
return res;
14261488
}
1489+
// We don't expect preview mode (i.e. --enable-preview) to affect module visibility.
14271490
jlong size;
1428-
const char *jimage_version = get_jimage_version_string();
1429-
return (*JImageFindResource)(JImage_file, module_name, jimage_version, "module-info.class", &size) != 0;
1491+
return jimage_find_resource(module_name, "module-info.class", /* is_preview */ false, &size) != 0;
14301492
}
14311493

14321494
jlong ClassLoader::classloader_time_ms() {

0 commit comments

Comments
 (0)