mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8308184: Launching java with large number of jars in classpath with java.protocol.handler.pkgs system property set can lead to StackOverflowError
Reviewed-by: mchung, alanb
This commit is contained in:
parent
4d4706967d
commit
268ec61d4f
2 changed files with 143 additions and 3 deletions
|
@ -53,11 +53,9 @@ import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
import java.util.zip.CRC32;
|
import java.util.zip.CRC32;
|
||||||
|
@ -209,7 +207,9 @@ public class URLClassPath {
|
||||||
|
|
||||||
this.unopenedUrls = unopenedUrls;
|
this.unopenedUrls = unopenedUrls;
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.jarHandler = null;
|
// the application class loader uses the built-in protocol handler to avoid protocol
|
||||||
|
// handler lookup when opening JAR files on the class path.
|
||||||
|
this.jarHandler = new sun.net.www.protocol.jar.Handler();
|
||||||
this.acc = null;
|
this.acc = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
140
test/jdk/sun/misc/URLClassPath/LargeClasspathWithPkgPrefix.java
Normal file
140
test/jdk/sun/misc/URLClassPath/LargeClasspathWithPkgPrefix.java
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
import jdk.test.lib.JDKToolFinder;
|
||||||
|
import jdk.test.lib.compiler.CompilerUtils;
|
||||||
|
import jdk.test.lib.process.OutputAnalyzer;
|
||||||
|
import jdk.test.lib.process.ProcessTools;
|
||||||
|
import jdk.test.lib.util.JarBuilder;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8308184
|
||||||
|
* @summary Verify that an application can be launched when the classpath contains large number of
|
||||||
|
* jars and the java.protocol.handler.pkgs system property is set
|
||||||
|
* @library /test/lib/
|
||||||
|
* @build jdk.test.lib.util.JarBuilder jdk.test.lib.compiler.CompilerUtils
|
||||||
|
* jdk.test.lib.process.ProcessTools
|
||||||
|
* @run driver LargeClasspathWithPkgPrefix
|
||||||
|
*/
|
||||||
|
public class LargeClasspathWithPkgPrefix {
|
||||||
|
|
||||||
|
private static final Path CWD = Path.of(".");
|
||||||
|
|
||||||
|
private static final String JAVA_MAIN_CONTENT = """
|
||||||
|
public class Foo {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
if (args.length != 0) {
|
||||||
|
System.out.println("unexpected args: " + java.util.Arrays.toString(args));
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
System.out.println("Running application on Java version: "
|
||||||
|
+ System.getProperty("java.version"));
|
||||||
|
System.out.println("Application launched with java.protocol.handler.pkgs="
|
||||||
|
+ System.getProperty("java.protocol.handler.pkgs"));
|
||||||
|
System.out.println("Application launched with classpath: "
|
||||||
|
+ System.getProperty("java.class.path"));
|
||||||
|
System.out.println("Hello World");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
|
public static void main(final String[] args) throws Exception {
|
||||||
|
// dir to which the application main's .class file will be compiled to
|
||||||
|
Path classesDir = Files.createTempDirectory(CWD, "8308184-classes").toAbsolutePath();
|
||||||
|
// dir contains many jars
|
||||||
|
Path libDir = Files.createTempDirectory(CWD, "8308184-libs").toAbsolutePath();
|
||||||
|
Files.createDirectories(libDir);
|
||||||
|
|
||||||
|
// trivial jar file
|
||||||
|
Path jarPath = Path.of(libDir.toString(), "8308184-dummy.jar");
|
||||||
|
createJar(jarPath);
|
||||||
|
|
||||||
|
// create multiple such jar files in the lib dir
|
||||||
|
int numCopies = 750;
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
for (int i = 1; i <= numCopies; i++) {
|
||||||
|
Path dest = Path.of(libDir.toString(), "8308184-dummy-" + i + ".jar");
|
||||||
|
Files.copy(jarPath, dest);
|
||||||
|
}
|
||||||
|
long end = System.currentTimeMillis();
|
||||||
|
System.out.println("Created " + numCopies + " jars under " + libDir
|
||||||
|
+ ", took " + (end - start) + " milli seconds");
|
||||||
|
|
||||||
|
// create the application's main java file
|
||||||
|
Path fooJavaSrcFile = Path.of(classesDir.toString(), "Foo.java");
|
||||||
|
Files.writeString(fooJavaSrcFile, JAVA_MAIN_CONTENT);
|
||||||
|
|
||||||
|
// compile this java file
|
||||||
|
compile(fooJavaSrcFile, classesDir);
|
||||||
|
|
||||||
|
// Create the classpath string. It is important that the classes directory which contains
|
||||||
|
// application's main class, is at the end of the classpath (or too far into the classpath).
|
||||||
|
// The initial entries in the classpath should be jar files.
|
||||||
|
// constructed classpath is of the form -cp lib/*:classes/
|
||||||
|
// (the * in lib/* is parsed/interpreted by the java launcher and includes all jars in that
|
||||||
|
// directory)
|
||||||
|
String classpath = File.pathSeparator + libDir.toString() + "/*"
|
||||||
|
+ File.pathSeparator + classesDir.toString();
|
||||||
|
// launch the application
|
||||||
|
launchApplication(classpath);
|
||||||
|
// test passed successfully, we don't need the lib directory which has too many jars,
|
||||||
|
// anymore. we let the dir stay only if the test fails, for debug purpose
|
||||||
|
libDir.toFile().deleteOnExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// creates a trivial jar file
|
||||||
|
private static void createJar(Path p) throws Exception {
|
||||||
|
JarBuilder jb = new JarBuilder(p.toString());
|
||||||
|
jb.addEntry("foobar.txt", "foobar".getBytes());
|
||||||
|
jb.build();
|
||||||
|
System.out.println("Created jar at " + p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// compile <javaFile> to <destDir>
|
||||||
|
private static void compile(Path javaFile, Path destDir) throws Exception {
|
||||||
|
boolean compiled = CompilerUtils.compile(javaFile, destDir);
|
||||||
|
if (!compiled) {
|
||||||
|
// compilation failure log/reason would already be available on System.out/err
|
||||||
|
throw new AssertionError("Compilation failed for " + javaFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// java -Djava.protocol.handler.pkgs=foo.bar.some.nonexistent.pkg -cp <classpath> Foo
|
||||||
|
private static void launchApplication(String classPath) throws Exception {
|
||||||
|
String java = JDKToolFinder.getJDKTool("java");
|
||||||
|
ProcessBuilder pb = new ProcessBuilder(java,
|
||||||
|
"-Djava.protocol.handler.pkgs=foo.bar.some.nonexistent.pkg",
|
||||||
|
"-cp", classPath,
|
||||||
|
"Foo");
|
||||||
|
pb.directory(CWD.toFile());
|
||||||
|
System.out.println("Launching java application: " + pb.command());
|
||||||
|
OutputAnalyzer analyzer = ProcessTools.executeProcess(pb);
|
||||||
|
analyzer.shouldHaveExitValue(0);
|
||||||
|
analyzer.shouldContain("Hello World");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue