8169909: java agent fails to add to class path when the initial module is a named module
Reviewed-by: alanb
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java Sat Nov 19 12:22:35 2016 +0100
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java Sun Nov 20 07:57:57 2016 -0800
@@ -72,13 +72,13 @@
// If neither is specified then default to -cp <working directory>
// If -cp is not specified and -m is specified, the value of
// java.class.path is an empty string, then no class path.
- URLClassPath ucp = null;
+ URLClassPath ucp = new URLClassPath(new URL[0]);
String mainMid = System.getProperty("jdk.module.main");
String cp = System.getProperty("java.class.path");
if (cp == null)
cp = "";
if (mainMid == null || cp.length() > 0)
- ucp = toURLClassPath(cp);
+ addClassPathToUCP(cp, ucp);
// create the class loaders
BOOT_LOADER = new BootClassLoader(bcp);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/instrument/modules/AppendToClassPathModuleTest.java Sun Nov 20 07:57:57 2016 -0800
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016, 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
+ * @bug 8169909
+ * @library src /lib/testlibrary
+ * @build test/*
+ * @run shell AppendToClassPathModuleTest.sh
+ * @run main AppendToClassPathModuleTest
+ */
+
+import java.util.Map;
+import static jdk.testlibrary.ProcessTools.*;
+
+/**
+ * Launch a modular test with no class path and no CLASSPATH set.
+ * The java agent appends to the "hidden" directory to the class path
+ * at runtime.
+ */
+public class AppendToClassPathModuleTest {
+ public static void main(String... args) throws Throwable {
+ String modulepath = System.getProperty("test.module.path");
+ ProcessBuilder pb =
+ createJavaProcessBuilder("-javaagent:Agent.jar",
+ "--module-path", modulepath,
+ "-m", "test/jdk.test.Main");
+
+ // remove CLASSPATH environment variable
+ Map<String,String> env = pb.environment();
+ String value = env.remove("CLASSPATH");
+
+ int exitCode = executeCommand(pb).getExitValue();
+ if (exitCode != 0) {
+ throw new RuntimeException("Test failed: " + exitCode);
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/instrument/modules/AppendToClassPathModuleTest.sh Sun Nov 20 07:57:57 2016 -0800
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+#
+# Copyright (c) 2016, 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.
+#
+
+if [ "${TESTSRC}" = "" ]
+then
+ echo "TESTSRC not set. Test cannot execute. Failed."
+ exit 1
+fi
+echo "TESTSRC=${TESTSRC}"
+
+if [ "${TESTJAVA}" = "" ]
+then
+ echo "TESTJAVA not set. Test cannot execute. Failed."
+ exit 1
+fi
+echo "TESTJAVA=${TESTJAVA}"
+
+if [ "${COMPILEJAVA}" = "" ]
+then
+ COMPILEJAVA="${TESTJAVA}"
+fi
+echo "COMPILEJAVA=${COMPILEJAVA}"
+
+if [ "${TESTCLASSES}" = "" ]
+then
+ echo "TESTCLASSES not set. Test cannot execute. Failed."
+ exit 1
+fi
+
+echo "TESTCLASSES=${TESTCLASSES}"
+
+mkdir -p hidden
+${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
+ -d hidden ${TESTSRC}/../ExampleForClassPath.java
+
+mkdir -p classes
+${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
+ -d classes ${TESTSRC}/../InstrumentationHandoff.java
+
+echo "Manifest-Version: 1.0" > Agent.mf
+echo "Class-Path: hidden/" >> Agent.mf
+echo "Premain-Class: InstrumentationHandoff" >> Agent.mf
+
+${TESTJAVA}/bin/jar ${TESTTOOLVMOPTS} cvfm Agent.jar \
+ Agent.mf -C classes InstrumentationHandoff.class
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/instrument/modules/src/test/jdk/test/Main.java Sun Nov 20 07:57:57 2016 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+package jdk.test;
+
+/**
+ * Launched by AppendToClassPathModuleTest.
+ */
+public class Main {
+ public static void main(String... args) throws Exception {
+ // "java.class.path" system property is expected to be empty.
+ String value = System.getProperty("java.class.path");
+ if (!value.isEmpty()) {
+ throw new RuntimeException("Non-empty java.class.path=" + value);
+ }
+
+ // load the "hidden" class that should be loaded by the system loader
+ Class<?> c = Class.forName("ExampleForClassPath");
+ if (c.getClassLoader() != ClassLoader.getSystemClassLoader()) {
+ throw new RuntimeException(c + " loaderd by " + c.getClassLoader());
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/instrument/modules/src/test/module-info.java Sun Nov 20 07:57:57 2016 -0800
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module test {
+}
--- a/jdk/test/tools/launcher/modules/classpath/JavaClassPathTest.java Sat Nov 19 12:22:35 2016 +0100
+++ b/jdk/test/tools/launcher/modules/classpath/JavaClassPathTest.java Sun Nov 20 07:57:57 2016 -0800
@@ -21,12 +21,14 @@
* questions.
*/
+import java.io.BufferedWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.spi.ToolProvider;
import jdk.testlibrary.OutputAnalyzer;
import org.testng.annotations.BeforeTest;
@@ -42,6 +44,7 @@
* @summary Test the default class path if -Djava.class.path is set
* @library /lib/testlibrary
* @modules jdk.compiler
+ * jdk.jartool
* @build CompilerUtils jdk.testlibrary.*
* @run testng JavaClassPathTest
*/
@@ -50,6 +53,7 @@
private static final Path SRC_DIR = Paths.get(System.getProperty("test.src"),
"src");
private static final Path MODS_DIR = Paths.get("mods");
+ private static final Path LIB_DIR = Paths.get("lib");
private static final String TEST_MODULE = "m";
private static final String TEST_MAIN = "jdk.test.Main";
@@ -66,27 +70,47 @@
Path res = Paths.get("jdk/test/res.properties");
Files.createFile(res);
+
+ ToolProvider jartool = ToolProvider.findFirst("jar").orElseThrow(
+ () -> new RuntimeException("jar tool not found")
+ );
+
+ Path jarfile = LIB_DIR.resolve("m.jar");
+ Files.createDirectories(LIB_DIR);
+ assertTrue(jartool.run(System.out, System.err, "cfe",
+ jarfile.toString(), TEST_MAIN,
+ file.toString()) == 0);
+
+ Path manifest = LIB_DIR.resolve("manifest");
+ try (BufferedWriter writer = Files.newBufferedWriter(manifest)) {
+ writer.write("CLASS-PATH: lib/m.jar");
+ }
+ jarfile = LIB_DIR.resolve("m1.jar");
+ assertTrue(jartool.run(System.out, System.err, "cfme",
+ jarfile.toString(), manifest.toString(), TEST_MAIN,
+ file.toString()) == 0);
}
@DataProvider(name = "classpath")
public Object[][] classpath() {
return new Object[][]{
// true indicates that class path default to current working directory
- { "", true },
- { "-Djava.class.path", true },
- { "-Djava.class.path=", true },
- { "-Djava.class.path=.", true },
+ { "", "." },
+ { "-Djava.class.path", "." },
+ { "-Djava.class.path=", "" },
+ { "-Djava.class.path=.", "." },
};
}
@Test(dataProvider = "classpath")
- public void testUnnamedModule(String option, boolean expected) throws Throwable {
+ public void testUnnamedModule(String option, String expected) throws Throwable {
List<String> args = new ArrayList<>();
if (!option.isEmpty()) {
args.add(option);
}
args.add(TEST_MAIN);
- args.add(Boolean.toString(expected));
+ args.add(Boolean.toString(true));
+ args.add(expected);
assertTrue(execute(args).getExitValue() == 0);
}
@@ -95,15 +119,14 @@
public Object[][] moduleAndClassPath() {
return new Object[][]{
// true indicates that class path default to current working directory
- { "", false },
- { "-Djava.class.path", false },
- { "-Djava.class.path=", false },
- { "-Djava.class.path=.", true },
+ { "", "" },
+ { "-Djava.class.path", "" },
+ { "-Djava.class.path=", "" },
};
}
@Test(dataProvider = "moduleAndClassPath")
- public void testNamedModule(String option, boolean expected) throws Throwable {
+ public void testNamedModule(String option, String expected) throws Throwable {
List<String> args = new ArrayList<>();
if (!option.isEmpty()) {
args.add(option);
@@ -112,7 +135,61 @@
args.add(MODS_DIR.toString());
args.add("-m");
args.add(TEST_MODULE + "/" + TEST_MAIN);
- args.add(Boolean.toString(expected));
+ // not default to CWD
+ args.add(Boolean.toString(false));
+ args.add(expected);
+
+
+ assertTrue(execute(args).getExitValue() == 0);
+ }
+
+ @Test
+ public void testClassPath() throws Throwable {
+ List<String> args = new ArrayList<>();
+ args.add("-Djava.class.path=.");
+ args.add("--module-path");
+ args.add(MODS_DIR.toString());
+ args.add("-m");
+ args.add(TEST_MODULE + "/" + TEST_MAIN);
+ args.add(Boolean.toString(true));
+ args.add(".");
+
+ assertTrue(execute(args).getExitValue() == 0);
+ }
+
+ @Test
+ public void testJAR() throws Throwable {
+ String jarfile = LIB_DIR.resolve("m.jar").toString();
+ List<String> args = new ArrayList<>();
+ args.add("-jar");
+ args.add(jarfile);
+ args.add(Boolean.toString(false));
+ args.add(jarfile);
+
+ assertTrue(execute(args).getExitValue() == 0);
+ }
+
+ /*
+ * Test CLASS-PATH attribute in manifest
+ */
+ @Test
+ public void testClassPathAttribute() throws Throwable {
+ String jarfile = LIB_DIR.resolve("m1.jar").toString();
+
+ List<String> args = new ArrayList<>();
+ args.add("-jar");
+ args.add(jarfile);
+ args.add(Boolean.toString(false));
+ args.add(jarfile);
+
+ assertTrue(execute(args).getExitValue() == 0);
+
+ args.clear();
+ args.add("-cp");
+ args.add(jarfile);
+ args.add(TEST_MAIN);
+ args.add(Boolean.toString(false));
+ args.add(jarfile);
assertTrue(execute(args).getExitValue() == 0);
}
--- a/jdk/test/tools/launcher/modules/classpath/src/m/jdk/test/Main.java Sat Nov 19 12:22:35 2016 +0100
+++ b/jdk/test/tools/launcher/modules/classpath/src/m/jdk/test/Main.java Sun Nov 20 07:57:57 2016 -0800
@@ -29,13 +29,14 @@
static final String JAVA_CLASS_PATH = "java.class.path";
public static void main(String[] args) throws Exception {
+ boolean expected = args[0].equals("true");
+ String cpath = args.length > 1 ? args[1] : "";
String value = System.getProperty(JAVA_CLASS_PATH);
- if (value == null) {
- throw new RuntimeException(JAVA_CLASS_PATH + " is expected non-null" +
- " for compatibility");
+ if (!value.equals(cpath)) {
+ throw new RuntimeException(JAVA_CLASS_PATH + "=" + value +
+ " expected=" + cpath);
}
- boolean expected = args[0].equals("true");
ClassLoader loader = ClassLoader.getSystemClassLoader();
URL url = loader.getResource("jdk/test/res.properties");
if ((expected && url == null) || (!expected && url != null)) {