Skip to content

Commit 89ca89c

Browse files
committed
8338626: ClassLoaderExt::process_jar_manifest() should allow / separator on Windows
Reviewed-by: iklam, dholmes, matsaave
1 parent 3e0da58 commit 89ca89c

File tree

2 files changed

+81
-1
lines changed

2 files changed

+81
-1
lines changed

src/hotspot/share/classfile/classLoaderExt.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,15 @@ void ClassLoaderExt::process_jar_manifest(JavaThread* current, ClassPathEntry* e
213213
char sep = os::file_separator()[0];
214214
const char* dir_name = entry->name();
215215
const char* dir_tail = strrchr(dir_name, sep);
216+
#ifdef _WINDOWS
217+
// On Windows, we also support forward slash as the file separator when locating entries in the classpath entry.
218+
const char* dir_tail2 = strrchr(dir_name, '/');
219+
if (dir_tail == nullptr) {
220+
dir_tail = dir_tail2;
221+
} else if (dir_tail2 != nullptr && dir_tail2 > dir_tail) {
222+
dir_tail = dir_tail2;
223+
}
224+
#endif
216225
int dir_len;
217226
if (dir_tail == nullptr) {
218227
dir_len = 0;

test/hotspot/jtreg/runtime/cds/appcds/ClassPathAttr.java

+72-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@
3030
* @run driver/timeout=240 ClassPathAttr
3131
*/
3232

33+
import jdk.test.lib.Platform;
3334
import jdk.test.lib.cds.CDSTestUtils;
3435
import jdk.test.lib.process.OutputAnalyzer;
3536
import java.io.File;
@@ -82,6 +83,76 @@ static void testNormalOps() throws Exception {
8283
output.shouldMatch("checking shared classpath entry: .*cpattr2.jar");
8384
output.shouldMatch("checking shared classpath entry: .*cpattr3.jar");
8485
});
86+
87+
// Test handling of forward slash ('/') file separator when locating entries
88+
// in the classpath entry on Windows.
89+
// Skip the following test when CDS dynamic dump is enabled due to some
90+
// issue when converting a relative path to real path.
91+
if (Platform.isWindows() && !CDSTestUtils.DYNAMIC_DUMP) {
92+
// Test with relative path
93+
// Find the index to the dir before the jar file.
94+
int idx = jar1.lastIndexOf(File.separator);
95+
idx = jar1.substring(0, idx - 1).lastIndexOf(File.separator);
96+
// Setup jar directory and names.
97+
String jarDir = jar1.substring(0, idx);
98+
String jar1Name = jar1.substring(idx + 1);
99+
String jar4Name = jar4.substring(idx + 1);
100+
String newCp = jar1Name.replace("\\", "/") + File.pathSeparator + jar4Name.replace("\\", "/");
101+
102+
OutputAnalyzer out = TestCommon.testDump(jarDir, newCp, classlist, "-Xlog:class+path=info");
103+
if (i == 1) {
104+
out.shouldMatch("opened:.*cpattr1.jar"); // first jar on -cp
105+
} else {
106+
// first jar on -cp with long Class-Path: attribute
107+
out.shouldMatch("opened:.*cpattr1_long.jar");
108+
}
109+
// one of the jar in the Class-Path: attribute of cpattr1.jar
110+
out.shouldMatch("opened:.*cpattr2.jar");
111+
112+
TestCommon.runWithRelativePath(
113+
jarDir.replace("\\", "/"),
114+
"-Xlog:class+path,class+load",
115+
"-cp", newCp,
116+
"CpAttr1")
117+
.assertNormalExit(output -> {
118+
output.shouldMatch("checking shared classpath entry: .*cpattr2.jar");
119+
output.shouldMatch("checking shared classpath entry: .*cpattr3.jar");
120+
});
121+
122+
// Go one directory up.
123+
int idx2 = jar1.substring(0, idx - 1).lastIndexOf(File.separator);
124+
if (idx2 != -1) {
125+
// Setup jar directory and names.
126+
jarDir = jar1.substring(0, idx2);
127+
// Set relative path to jar containing '\' and '/' file separators
128+
// e.g. d1\d2/A.jar
129+
jar1Name = jar1.substring(idx2 + 1).replace("\\", "/");
130+
jar4Name = jar4.substring(idx2 + 1).replace("\\", "/");
131+
jar1Name = jar1Name.replaceFirst("/", "\\\\");
132+
jar4Name = jar4Name.replaceFirst("/", "\\\\");
133+
134+
newCp = jar1Name + File.pathSeparator + jar4Name;
135+
out = TestCommon.testDump(jarDir, newCp, classlist, "-Xlog:class+path=info");
136+
if (i == 1) {
137+
out.shouldMatch("opened:.*cpattr1.jar"); // first jar on -cp
138+
} else {
139+
// first jar on -cp with long Class-Path: attribute
140+
out.shouldMatch("opened:.*cpattr1_long.jar");
141+
}
142+
// one of the jar in the Class-Path: attribute of cpattr1.jar
143+
out.shouldMatch("opened:.*cpattr2.jar");
144+
145+
TestCommon.runWithRelativePath(
146+
jarDir.replace("\\", "/"),
147+
"-Xlog:class+path,class+load",
148+
"-cp", newCp,
149+
"CpAttr1")
150+
.assertNormalExit(output -> {
151+
output.shouldMatch("checking shared classpath entry: .*cpattr2.jar");
152+
output.shouldMatch("checking shared classpath entry: .*cpattr3.jar");
153+
});
154+
}
155+
}
85156
}
86157

87158
// test duplicate jars in the "Class-path" attribute in the jar manifest

0 commit comments

Comments
 (0)