8168205: Should not default class path to CWD if -cp is not specified but -m is specified

Reviewed-by: alanb
This commit is contained in:
Mandy Chung 2016-10-27 13:42:12 -07:00
parent abea796b35
commit fc99db2ced
8 changed files with 233 additions and 34 deletions

View File

@ -1681,6 +1681,15 @@ public abstract class ClassLoader {
* this method during startup should take care not to cache the return
* value until the system is fully initialized.
*
* <p> The class path used by the built-in system class loader is determined
* by the system property "{@code java.class.path}" during early
* initialization of the VM. If the system property is not defined,
* or its value is an empty string, then there is no class path
* when the initial module is a module on the application module path,
* i.e. <em>a named module</em>. If the initial module is not on
* the application module path then the class path defaults to
* the current working directory.
*
* @return The system <tt>ClassLoader</tt> for delegation
*
* @throws SecurityException

View File

@ -69,16 +69,17 @@ public class ClassLoaders {
bcp = toURLClassPath(s);
// we have a class path if -cp is specified or -m is not specified.
// If neither is specified then default to -cp <working directory>.
// 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;
String mainMid = System.getProperty("jdk.module.main");
String cp = System.getProperty("java.class.path");
if (mainMid == null && cp == null)
if (cp == null)
cp = "";
if (cp != null)
if (mainMid == null || cp.length() > 0)
ucp = toURLClassPath(cp);
// create the class loaders
BOOT_LOADER = new BootClassLoader(bcp);
PLATFORM_LOADER = new PlatformClassLoader(BOOT_LOADER);

View File

@ -51,16 +51,6 @@ static const char* const_progname = PROGNAME;
static char* const_progname = NULL;
#endif
static const char* const_jargs[] = JAVA_ARGS;
/*
* ApplicationHome is prepended to each of these entries; the resulting
* strings are concatenated (separated by PATH_SEPARATOR) and used as the
* value of -cp option to the launcher.
*/
#ifndef APP_CLASSPATH
static const char* const_appclasspath[] = { NULL };
#else
static const char* const_appclasspath[] = APP_CLASSPATH;
#endif /* APP_CLASSPATH */
#else /* !JAVA_ARGS */
#define HAS_JAVA_ARGS JNI_FALSE
static const char* const_progname = "java";

View File

@ -83,7 +83,7 @@ char **__initenv;
int WINAPI
WinMain(HINSTANCE inst, HINSTANCE previnst, LPSTR cmdline, int cmdshow)
{
int margc, appclassc;
int margc;
char** margv;
const jboolean const_javaw = JNI_TRUE;
@ -93,7 +93,7 @@ WinMain(HINSTANCE inst, HINSTANCE previnst, LPSTR cmdline, int cmdshow)
int
main(int argc, char **argv)
{
int margc, appclassc;
int margc;
char** margv;
const jboolean const_javaw = JNI_FALSE;
#endif /* JAVAW */
@ -148,14 +148,9 @@ main(int argc, char **argv)
margv = args->elements;
}
#endif /* WIN32 */
if (const_appclasspath[0] == NULL) {
appclassc = 0;
} else {
appclassc = sizeof(const_appclasspath) / sizeof(char *);
}
return JLI_Launch(margc, margv,
sizeof(const_jargs) / sizeof(char *), const_jargs,
appclassc, const_appclasspath,
0, NULL,
VERSION_STRING,
DOT_VERSION,
(const_progname != NULL) ? const_progname : *margv,

View File

@ -1664,19 +1664,21 @@ AddApplicationOptions(int cpathc, const char **cpathv)
AddOption(apphome, NULL);
/* How big is the application's classpath? */
size = 40; /* 40: "-Djava.class.path=" */
for (i = 0; i < cpathc; i++) {
size += (int)JLI_StrLen(home) + (int)JLI_StrLen(cpathv[i]) + 1; /* 1: separator */
if (cpathc > 0) {
size = 40; /* 40: "-Djava.class.path=" */
for (i = 0; i < cpathc; i++) {
size += (int)JLI_StrLen(home) + (int)JLI_StrLen(cpathv[i]) + 1; /* 1: separator */
}
appcp = (char *)JLI_MemAlloc(size + 1);
JLI_StrCpy(appcp, "-Djava.class.path=");
for (i = 0; i < cpathc; i++) {
JLI_StrCat(appcp, home); /* c:\program files\myapp */
JLI_StrCat(appcp, cpathv[i]); /* \lib\myapp.jar */
JLI_StrCat(appcp, separator); /* ; */
}
appcp[JLI_StrLen(appcp)-1] = '\0'; /* remove trailing path separator */
AddOption(appcp, NULL);
}
appcp = (char *)JLI_MemAlloc(size + 1);
JLI_StrCpy(appcp, "-Djava.class.path=");
for (i = 0; i < cpathc; i++) {
JLI_StrCat(appcp, home); /* c:\program files\myapp */
JLI_StrCat(appcp, cpathv[i]); /* \lib\myapp.jar */
JLI_StrCat(appcp, separator); /* ; */
}
appcp[JLI_StrLen(appcp)-1] = '\0'; /* remove trailing path separator */
AddOption(appcp, NULL);
return JNI_TRUE;
}

View File

@ -0,0 +1,131 @@
/*
* 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.
*/
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 jdk.testlibrary.OutputAnalyzer;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.testng.Assert.assertTrue;
import static jdk.testlibrary.ProcessTools.*;
/**
* @test
* @bug 8168205
* @summary Test the default class path if -Djava.class.path is set
* @library /lib/testlibrary
* @modules jdk.compiler
* @build CompilerUtils jdk.testlibrary.*
* @run testng JavaClassPathTest
*/
public class JavaClassPathTest {
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 String TEST_MODULE = "m";
private static final String TEST_MAIN = "jdk.test.Main";
@BeforeTest
public void setup() throws Exception {
boolean compiled = CompilerUtils.compile(SRC_DIR.resolve(TEST_MODULE),
MODS_DIR.resolve(TEST_MODULE));
assertTrue(compiled, "module " + TEST_MODULE + " did not compile");
// add the class and a resource to the current working directory
Path file = Paths.get("jdk/test/Main.class");
Files.createDirectories(file.getParent());
Files.copy(MODS_DIR.resolve(TEST_MODULE).resolve(file), file);
Path res = Paths.get("jdk/test/res.properties");
Files.createFile(res);
}
@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 },
};
}
@Test(dataProvider = "classpath")
public void testUnnamedModule(String option, boolean expected) throws Throwable {
List<String> args = new ArrayList<>();
if (!option.isEmpty()) {
args.add(option);
}
args.add(TEST_MAIN);
args.add(Boolean.toString(expected));
assertTrue(execute(args).getExitValue() == 0);
}
@DataProvider(name = "moduleAndClassPath")
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 },
};
}
@Test(dataProvider = "moduleAndClassPath")
public void testNamedModule(String option, boolean expected) throws Throwable {
List<String> args = new ArrayList<>();
if (!option.isEmpty()) {
args.add(option);
}
args.add("--module-path");
args.add(MODS_DIR.toString());
args.add("-m");
args.add(TEST_MODULE + "/" + TEST_MAIN);
args.add(Boolean.toString(expected));
assertTrue(execute(args).getExitValue() == 0);
}
private OutputAnalyzer execute(List<String> options) throws Throwable {
ProcessBuilder pb =
createJavaProcessBuilder(options.toArray(new String[0]));
Map<String,String> env = pb.environment();
// remove CLASSPATH environment variable
String value = env.remove("CLASSPATH");
return executeCommand(pb)
.outputTo(System.out)
.errorTo(System.out);
}
}

View File

@ -0,0 +1,45 @@
/**
* 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;
import java.net.URL;
public class Main {
static final String JAVA_CLASS_PATH = "java.class.path";
public static void main(String[] args) throws Exception {
String value = System.getProperty(JAVA_CLASS_PATH);
if (value == null) {
throw new RuntimeException(JAVA_CLASS_PATH + " is expected non-null" +
" for compatibility");
}
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)) {
throw new RuntimeException("URL: " + url + " expected non-null: " + expected);
}
}
}

View File

@ -0,0 +1,26 @@
/*
* 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 m {
}