# HG changeset patch # User ccheung # Date 1547244357 28800 # Node ID b7dca420fa0cfa2e302422b719172f4277185d70 # Parent fbc921683f02134c160923bb150ebeedc7bdfc0d 8216184: CDS/appCDS tests failed on Windows due to long path to a classlist file Summary: use os::open() instead of fopen() Reviewed-by: iklam, dholmes diff -r fbc921683f02 -r b7dca420fa0c src/hotspot/share/classfile/classListParser.cpp --- a/src/hotspot/share/classfile/classListParser.cpp Fri Jan 11 13:34:57 2019 +0100 +++ b/src/hotspot/share/classfile/classListParser.cpp Fri Jan 11 14:05:57 2019 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, 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 @@ -47,7 +47,15 @@ assert(_instance == NULL, "must be singleton"); _instance = this; _classlist_file = file; - _file = fopen(file, "r"); + _file = NULL; + // Use os::open() because neither fopen() nor os::fopen() + // can handle long path name on Windows. + int fd = os::open(file, O_RDONLY, S_IREAD); + if (fd != -1) { + // Obtain a File* from the file descriptor so that fgets() + // can be used in parse_one_line() + _file = os::open(fd, "r"); + } if (_file == NULL) { char errmsg[JVM_MAXPATHLEN]; os::lasterror(errmsg, JVM_MAXPATHLEN); diff -r fbc921683f02 -r b7dca420fa0c src/hotspot/share/memory/metaspaceShared.cpp --- a/src/hotspot/share/memory/metaspaceShared.cpp Fri Jan 11 13:34:57 2019 +0100 +++ b/src/hotspot/share/memory/metaspaceShared.cpp Fri Jan 11 14:05:57 2019 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, 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 @@ -1659,7 +1659,6 @@ ResourceMark rm; char class_list_path_str[JVM_MAXPATHLEN]; // Preload classes to be shared. - // Should use some os:: method rather than fopen() here. aB. const char* class_list_path; if (SharedClassListFile == NULL) { // Construct the path to the class list (in jre/lib) diff -r fbc921683f02 -r b7dca420fa0c test/hotspot/jtreg/runtime/appcds/LongClassListPath.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/runtime/appcds/LongClassListPath.java Fri Jan 11 14:05:57 2019 -0800 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2019, 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 Test the handling of long path to the classlist file. + * @requires vm.cds + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @compile test-classes/Hello.java + * @run driver LongClassListPath + */ + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.Arrays; +import jdk.test.lib.cds.CDSOptions; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.process.OutputAnalyzer; + +public class LongClassListPath { + private static final int MAX_PATH = 260; + public static void main(String[] args) throws Exception { + String[] classes = {"hello"}; + String classList = + CDSTestUtils.makeClassList(classes).getPath(); + String archiveName = "LongClassListPath.jsa"; + + // Create a directory with long path and copy the classlist file to + // the directory. + Path classDir = Paths.get(System.getProperty("test.classes")); + Path destDir = classDir; + int subDirLen = MAX_PATH - classDir.toString().length() - 2; + if (subDirLen > 0) { + char[] chars = new char[subDirLen]; + Arrays.fill(chars, 'x'); + String subPath = new String(chars); + destDir = Paths.get(System.getProperty("test.classes"), subPath); + } + File longDir = destDir.toFile(); + longDir.mkdir(); + String destClassList = longDir.getPath() + File.separator + "LongClassListPath.classlist"; + Files.copy(Paths.get(classList), Paths.get(destClassList), StandardCopyOption.REPLACE_EXISTING); + + CDSOptions opts = (new CDSOptions()) + .addPrefix("-XX:ExtraSharedClassListFile=" + destClassList, "-cp", JarBuilder.getOrCreateHelloJar()) + .setArchiveName(archiveName); + CDSTestUtils.createArchiveAndCheck(opts); + } +} diff -r fbc921683f02 -r b7dca420fa0c test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/DummyClassesInBootClassPath.java --- a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/DummyClassesInBootClassPath.java Fri Jan 11 13:34:57 2019 +0100 +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/DummyClassesInBootClassPath.java Fri Jan 11 14:05:57 2019 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, 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 @@ -63,6 +63,8 @@ String appJar = TestCommon.getTestJar("dummyClasses.jar"); OutputAnalyzer dumpOutput = TestCommon.dump( appJar, classNames, "-Xbootclasspath/a:" + appJar); + TestCommon.checkDump(dumpOutput); + List argsList = new ArrayList(); for (int i = 0; i < classNames.length; i++) { argsList.add(classNames[i].replace('/', '.'));