mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
8356308: Assert with -Xlog:class+path when classpath has an empty element
Reviewed-by: dholmes, ccheung
This commit is contained in:
parent
8b6a11f7e0
commit
bce2bd24ef
@ -464,6 +464,7 @@ void AOTClassLocationConfig::dumptime_init_helper(TRAPS) {
|
||||
AOTClassLocation* jrt = AOTClassLocation::allocate(THREAD, ClassLoader::get_jrt_entry()->name(),
|
||||
0, Group::MODULES_IMAGE,
|
||||
/*from_cpattr*/false, /*is_jrt*/true);
|
||||
log_info(class, path)("path [%d] = (modules image)", tmp_array.length());
|
||||
tmp_array.append(jrt);
|
||||
|
||||
parse(THREAD, tmp_array, all_css.boot_cp(), Group::BOOT_CLASSPATH, /*parse_manifest*/true);
|
||||
@ -573,6 +574,7 @@ void AOTClassLocationConfig::parse(JavaThread* current, GrowableClassLocationArr
|
||||
void AOTClassLocationConfig::add_class_location(JavaThread* current, GrowableClassLocationArray& tmp_array,
|
||||
const char* path, Group group, bool parse_manifest, bool from_cpattr) {
|
||||
AOTClassLocation* cs = AOTClassLocation::allocate(current, path, tmp_array.length(), group, from_cpattr);
|
||||
log_info(class, path)("path [%d] = %s%s", tmp_array.length(), path, from_cpattr ? " (from cpattr)" : "");
|
||||
tmp_array.append(cs);
|
||||
|
||||
if (!parse_manifest) {
|
||||
@ -726,6 +728,8 @@ bool AOTClassLocationConfig::is_valid_classpath_index(int classpath_index, Insta
|
||||
}
|
||||
|
||||
AOTClassLocationConfig* AOTClassLocationConfig::write_to_archive() const {
|
||||
log_locations(CDSConfig::output_archive_path(), /*is_write=*/true);
|
||||
|
||||
Array<AOTClassLocation*>* archived_copy = ArchiveBuilder::new_ro_array<AOTClassLocation*>(_class_locations->length());
|
||||
for (int i = 0; i < _class_locations->length(); i++) {
|
||||
archived_copy->at_put(i, _class_locations->at(i)->write_to_archive());
|
||||
@ -773,7 +777,7 @@ bool AOTClassLocationConfig::check_classpaths(bool is_boot_classpath, bool has_a
|
||||
effective_dumptime_path = substitute(effective_dumptime_path, _dumptime_lcp_len, runtime_lcp, runtime_lcp_len);
|
||||
}
|
||||
|
||||
log_info(class, path)("Checking '%s' %s%s", effective_dumptime_path, cs->file_type_string(),
|
||||
log_info(class, path)("Checking [%d] '%s' %s%s", i, effective_dumptime_path, cs->file_type_string(),
|
||||
cs->from_cpattr() ? " (from JAR manifest ClassPath attribute)" : "");
|
||||
if (!cs->from_cpattr() && file_exists(effective_dumptime_path)) {
|
||||
if (!runtime_css.has_next()) {
|
||||
@ -961,11 +965,14 @@ bool AOTClassLocationConfig::need_lcp_match_helper(int start, int end, ClassLoca
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AOTClassLocationConfig::validate(bool has_aot_linked_classes, bool* has_extra_module_paths) const {
|
||||
bool AOTClassLocationConfig::validate(const char* cache_filename, bool has_aot_linked_classes, bool* has_extra_module_paths) const {
|
||||
ResourceMark rm;
|
||||
AllClassLocationStreams all_css;
|
||||
|
||||
log_locations(cache_filename, /*is_write=*/false);
|
||||
|
||||
const char* jrt = ClassLoader::get_jrt_entry()->name();
|
||||
log_info(class, path)("Checking [0] (modules image)");
|
||||
bool success = class_location_at(0)->check(jrt, has_aot_linked_classes);
|
||||
log_info(class, path)("Modules image %s validation: %s", jrt, success ? "passed" : "failed");
|
||||
if (!success) {
|
||||
@ -1036,6 +1043,17 @@ bool AOTClassLocationConfig::validate(bool has_aot_linked_classes, bool* has_ext
|
||||
return success;
|
||||
}
|
||||
|
||||
void AOTClassLocationConfig::log_locations(const char* cache_filename, bool is_write) const {
|
||||
if (log_is_enabled(Info, class, path)) {
|
||||
LogStreamHandle(Info, class, path) st;
|
||||
st.print_cr("%s classpath(s) %s %s (size = %d)",
|
||||
is_write ? "Writing" : "Reading",
|
||||
is_write ? "into" : "from",
|
||||
cache_filename, class_locations()->length());
|
||||
print_on(&st);
|
||||
}
|
||||
}
|
||||
|
||||
void AOTClassLocationConfig::print() {
|
||||
if (CDSConfig::is_dumping_archive()) {
|
||||
tty->print_cr("AOTClassLocationConfig::_dumptime_instance = %p", _dumptime_instance);
|
||||
@ -1052,8 +1070,15 @@ void AOTClassLocationConfig::print() {
|
||||
}
|
||||
|
||||
void AOTClassLocationConfig::print_on(outputStream* st) const {
|
||||
const char* type = "boot";
|
||||
int n = class_locations()->length();
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (i >= boot_cp_end_index()) {
|
||||
type = "app";
|
||||
}
|
||||
if (i >= app_cp_end_index()) {
|
||||
type = "module";
|
||||
}
|
||||
const AOTClassLocation* cs = class_location_at(i);
|
||||
const char* path;
|
||||
if (i == 0) {
|
||||
@ -1061,12 +1086,6 @@ void AOTClassLocationConfig::print_on(outputStream* st) const {
|
||||
} else {
|
||||
path = cs->path();
|
||||
}
|
||||
st->print_cr("[%d] = %s", i, path);
|
||||
if (i == boot_cp_end_index() && i < n) {
|
||||
st->print_cr("--- end of boot");
|
||||
}
|
||||
if (i == app_cp_end_index() && i < n) {
|
||||
st->print_cr("--- end of app");
|
||||
}
|
||||
st->print_cr("(%-6s) [%d] = %s", type, i, path);
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,6 +204,7 @@ class AOTClassLocationConfig : public CHeapObj<mtClassShared> {
|
||||
const char* prepend, size_t prepend_len) const;
|
||||
|
||||
void print_on(outputStream* st) const;
|
||||
void log_locations(const char* cache_filename, bool is_writing) const;
|
||||
|
||||
public:
|
||||
static AOTClassLocationConfig* dumptime() {
|
||||
@ -269,7 +270,7 @@ public:
|
||||
AOTClassLocationConfig* write_to_archive() const;
|
||||
|
||||
// Functions used only during runtime
|
||||
bool validate(bool has_aot_linked_classes, bool* has_extra_module_paths) const;
|
||||
bool validate(const char* cache_filename, bool has_aot_linked_classes, bool* has_extra_module_paths) const;
|
||||
|
||||
bool is_valid_classpath_index(int classpath_index, InstanceKlass* ik);
|
||||
|
||||
|
||||
@ -325,7 +325,7 @@ bool FileMapInfo::validate_class_location() {
|
||||
|
||||
AOTClassLocationConfig* config = header()->class_location_config();
|
||||
bool has_extra_module_paths = false;
|
||||
if (!config->validate(header()->has_aot_linked_classes(), &has_extra_module_paths)) {
|
||||
if (!config->validate(full_path(), header()->has_aot_linked_classes(), &has_extra_module_paths)) {
|
||||
if (PrintSharedArchiveAndExit) {
|
||||
MetaspaceShared::set_archive_loading_failed();
|
||||
return true;
|
||||
|
||||
@ -26,18 +26,40 @@
|
||||
#include "runtime/os.hpp"
|
||||
#include "utilities/classpathStream.hpp"
|
||||
|
||||
const char* ClasspathStream::get_next() {
|
||||
while (_class_path[_end] != '\0' && _class_path[_end] != os::path_separator()[0]) {
|
||||
_end++;
|
||||
ClasspathStream::ClasspathStream(const char* classpath) {
|
||||
_cp = classpath;
|
||||
skip_blank_paths();
|
||||
}
|
||||
|
||||
char ClasspathStream::separator() {
|
||||
// All supported platforms have a single character path separator.
|
||||
return os::path_separator()[0];
|
||||
}
|
||||
|
||||
void ClasspathStream::skip_blank_paths() {
|
||||
while (*_cp == separator()) {
|
||||
_cp++;
|
||||
}
|
||||
int path_len = _end - _start;
|
||||
}
|
||||
|
||||
const char* ClasspathStream::get_next() {
|
||||
assert(has_next(), "call this only after you checked has_next()");
|
||||
assert(*_cp != separator(), "ensured by constructor and get_next()");
|
||||
|
||||
const char* end = _cp + 1;
|
||||
while (*end != separator() && *end != '\0') {
|
||||
end++;
|
||||
}
|
||||
|
||||
int path_len = end - _cp;
|
||||
char* path = NEW_RESOURCE_ARRAY(char, path_len + 1);
|
||||
strncpy(path, &_class_path[_start], path_len);
|
||||
strncpy(path, _cp, path_len);
|
||||
path[path_len] = '\0';
|
||||
|
||||
while (_class_path[_end] == os::path_separator()[0]) {
|
||||
_end++;
|
||||
}
|
||||
_start = _end;
|
||||
assert(strlen(path) > 0, "must be");
|
||||
|
||||
_cp = end;
|
||||
skip_blank_paths();
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,23 +26,20 @@
|
||||
#define SHARE_UTILITIES_CLASSPATHSTREAM_HPP
|
||||
|
||||
class ClasspathStream : public StackObj {
|
||||
const char* _class_path;
|
||||
int _len;
|
||||
int _start;
|
||||
int _end;
|
||||
|
||||
const char* _cp;
|
||||
static char separator();
|
||||
void skip_blank_paths();
|
||||
public:
|
||||
ClasspathStream(const char* class_path) {
|
||||
_class_path = class_path;
|
||||
_len = (int)strlen(class_path);
|
||||
_start = 0;
|
||||
_end = 0;
|
||||
}
|
||||
// The caller should ensure that class_path is alive during the
|
||||
// lifetime of this ClasspathStream.
|
||||
ClasspathStream(const char* class_path);
|
||||
|
||||
bool has_next() {
|
||||
return _start < _len;
|
||||
return *_cp != '\0';
|
||||
}
|
||||
|
||||
// Call this only after you checked has_next().
|
||||
// Returns a resource-allocated string.
|
||||
const char* get_next();
|
||||
};
|
||||
|
||||
|
||||
@ -59,9 +59,9 @@ public class PrintSharedArchiveAndExit {
|
||||
String appJar = JarBuilder.getOrCreateHelloJar();
|
||||
String appJar2 = JarBuilder.build("PrintSharedArchiveAndExit-more", "HelloMore");
|
||||
String cp = appJar + File.pathSeparator + appJar2;
|
||||
String firstCheckShortMsg = "Checking 'hello.jar' file"; // the first JAR to check (without directory prefix)
|
||||
String firstCheckMsg = "Checking '" + appJar + "' file"; // the first JAR to check
|
||||
String lastCheckMsg = "Checking '" + appJar2 + "' file"; // the last JAR to check
|
||||
String firstCheckShortMsg = "Checking [1] 'hello.jar' file"; // the first JAR to check (without directory prefix)
|
||||
String firstCheckMsg = "Checking [1] '" + appJar + "' file"; // the first JAR to check
|
||||
String lastCheckMsg = "Checking [2] '" + appJar2 + "' file"; // the last JAR to check
|
||||
|
||||
TestCommon.testDump(cp, TestCommon.list("Hello", "HelloMore"));
|
||||
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary verify the output of -Xlog:class+path when using AOT cache
|
||||
* @bug 8356308
|
||||
* @requires vm.cds.supports.aot.class.linking
|
||||
* @requires vm.flagless
|
||||
* @library /test/lib
|
||||
* @build ClassPathLogging
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar ClassPathLoggingApp
|
||||
* @run driver ClassPathLogging
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import jdk.test.lib.cds.SimpleCDSAppTester;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
public class ClassPathLogging {
|
||||
public static void main(String... args) throws Exception {
|
||||
String sep = File.pathSeparator;
|
||||
SimpleCDSAppTester.of("ClassPathLogging")
|
||||
.addVmArgs("-Xlog:class+path=debug")
|
||||
.classpath(sep + "foo.jar" + sep + sep + sep + "app.jar" + sep) // all empty paths should be skipped.
|
||||
.appCommandLine("ClassPathLoggingApp")
|
||||
.setProductionChecker((OutputAnalyzer out) -> {
|
||||
out.shouldContain("HelloWorld")
|
||||
.shouldContain("Reading classpath(s) from ClassPathLogging.aot (size = 3)")
|
||||
.shouldMatch("boot.*0.*=.*modules")
|
||||
.shouldContain("(app ) [1] = foo.jar")
|
||||
.shouldContain("(app ) [2] = app.jar");
|
||||
})
|
||||
.runAOTWorkflow();
|
||||
}
|
||||
}
|
||||
|
||||
class ClassPathLoggingApp {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("HelloWorld");
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user