# HG changeset patch # User sla # Date 1396881916 -7200 # Mon Apr 07 16:45:16 2014 +0200 # Node ID 400cfcb2b32507d1aea528e417430c34ad78bc4c # Parent 85df9a94d1f0aa46e2a9a3fb82d17c9e677be9f6 [mq]: 8033104-jvmstat diff --git a/make/mapfiles/libjava/mapfile-vers b/make/mapfiles/libjava/mapfile-vers --- a/make/mapfiles/libjava/mapfile-vers +++ b/make/mapfiles/libjava/mapfile-vers @@ -273,7 +273,8 @@ Java_sun_misc_VM_isSetUID; Java_sun_misc_VM_initialize; Java_sun_misc_VMSupport_initAgentProperties; - + Java_sun_misc_VMSupport_getVMTemporaryDirectory; + # ZipFile.c needs this one throwFileNotFoundException; diff --git a/src/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/PerfDataFile.java b/src/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/PerfDataFile.java --- a/src/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/PerfDataFile.java +++ b/src/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/PerfDataFile.java @@ -233,8 +233,6 @@ * does not conform to the expected pattern */ public static int getLocalVmId(File file) { - int lvmid = 0; - try { // try 1.4.2 and later format first return Integer.parseInt(file.getName()); @@ -287,31 +285,13 @@ return tmpDirName + dirNamePrefix + user + File.separator; } - /* - * this static initializer would not be necessary if the - * Solaris java.io.tmpdir property were set to /tmp by default - */ static { /* - * Why is java.io.tmpdir on Solaris set to "/var/tmp/" when the - * HotSpot JVM os:get_temp_path() method returns "/tmp/" - * - * Why do Solaris and Windows return a string with a trailing - * file separator character where as Linix does not? (this change - * seems to have occurred sometime during hopper beta) + * For this to work, the target VM and this code need to use + * the same directory. Instead of guessing which directory the + * VM is using, we will ask. */ - String tmpdir = System.getProperty("java.io.tmpdir"); - - if (tmpdir.compareTo("/var/tmp/") == 0) { - /* - * shared memory files are created in /tmp. Interestingly, - * java.io.tmpdir is set to "/var/tmp/" on Solaris and Linux, - * but os::get_temp_directory() is set to "/tmp/" on these - * platforms. the java.io.logging packages also makes reference - * to java.io.tmpdir. - */ - tmpdir = "/tmp/"; - } + String tmpdir = sun.misc.VMSupport.getVMTemporaryDirectory(); /* * Assure that the string returned has a trailing File.separator diff --git a/src/share/classes/sun/misc/VMSupport.java b/src/share/classes/sun/misc/VMSupport.java --- a/src/share/classes/sun/misc/VMSupport.java +++ b/src/share/classes/sun/misc/VMSupport.java @@ -97,4 +97,14 @@ throw new RuntimeException(ioe.getMessage()); } } + + /* + * Return the temporary directory that the VM uses for the attach + * and perf data files. + * + * It is important that this directory is well-known and the + * same for all VM instances. It cannot be affected by configuration + * variables such as java.io.tmpdir. + */ + public static native String getVMTemporaryDirectory(); } diff --git a/src/share/javavm/export/jvm.h b/src/share/javavm/export/jvm.h --- a/src/share/javavm/export/jvm.h +++ b/src/share/javavm/export/jvm.h @@ -111,6 +111,9 @@ JNIEXPORT jobject JNICALL JVM_InitProperties(JNIEnv *env, jobject p); +JNIEXPORT jstring JNICALL +JVM_GetTemporaryDirectory(JNIEnv *env); + /* * java.io.File */ diff --git a/src/share/native/sun/misc/VMSupport.c b/src/share/native/sun/misc/VMSupport.c --- a/src/share/native/sun/misc/VMSupport.c +++ b/src/share/native/sun/misc/VMSupport.c @@ -53,3 +53,9 @@ } return (*InitAgentProperties_fp)(env, props); } + +JNIEXPORT jstring JNICALL +Java_sun_misc_VMSupport_getVMTemporaryDirectory(JNIEnv *env, jclass cls) +{ + return JVM_GetTemporaryDirectory(env); +} diff --git a/test/com/sun/tools/attach/BasicTests.java b/test/com/sun/tools/attach/BasicTests.java --- a/test/com/sun/tools/attach/BasicTests.java +++ b/test/com/sun/tools/attach/BasicTests.java @@ -38,7 +38,7 @@ * @bug 6173612 6273707 6277253 6335921 6348630 6342019 6381757 * @summary Basic unit tests for the VM attach mechanism. * @library /lib/testlibrary - * @run build Agent BadAgent RedefineAgent Application Shutdown RedefineDummy + * @run build Agent BadAgent RedefineAgent Application Shutdown RedefineDummy RunnerUtil * @run main BasicTests * * This test will perform a number of basic attach tests. @@ -238,19 +238,17 @@ // Test 6 - list method should list the target VM System.out.println(" - Test: VirtualMachine.list"); List l = VirtualMachine.list(); - if (!l.isEmpty()) { - boolean found = false; - for (VirtualMachineDescriptor vmd: l) { - if (vmd.id().equals(pid)) { - found = true; - break; - } + boolean found = false; + for (VirtualMachineDescriptor vmd: l) { + if (vmd.id().equals(pid)) { + found = true; + break; } - if (found) { - System.out.println(" - " + pid + " found."); - } else { - throw new RuntimeException(pid + " not found in VM list"); - } + } + if (found) { + System.out.println(" - " + pid + " found."); + } else { + throw new RuntimeException(pid + " not found in VM list"); } // test 7 - basic hashCode/equals tests diff --git a/test/com/sun/tools/attach/RunnerUtil.java b/test/com/sun/tools/attach/RunnerUtil.java --- a/test/com/sun/tools/attach/RunnerUtil.java +++ b/test/com/sun/tools/attach/RunnerUtil.java @@ -24,12 +24,11 @@ import java.io.IOException; import java.io.File; import java.nio.file.Files; -import java.nio.file.Path; import java.util.Arrays; import java.util.regex.Pattern; import java.util.regex.Matcher; + import jdk.testlibrary.OutputAnalyzer; -import jdk.testlibrary.JDKToolLauncher; import jdk.testlibrary.ProcessTools; import jdk.testlibrary.Utils; import jdk.testlibrary.ProcessThread; @@ -39,6 +38,7 @@ * (Test runner = class that launch a test) */ public class RunnerUtil { + /** * The Application process must be run concurrently with our tests since * the tests will attach to the Application. @@ -49,16 +49,31 @@ * * The Application will write its pid and shutdownPort in the given outFile. */ - public static ProcessThread startApplication(String outFile) throws Throwable { + public static ProcessThread startApplication(String outFile, String... additionalOpts) throws Throwable { String classpath = System.getProperty("test.class.path", "."); - String[] args = Utils.addTestJavaOpts( - "-Dattach.test=true", "-classpath", classpath, "Application", outFile); + String[] myArgs = concat(additionalOpts, new String [] { "-Dattach.test=true", "-classpath", classpath, "Application", outFile }); + String[] args = Utils.addTestJavaOpts(myArgs); ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args); ProcessThread pt = new ProcessThread("runApplication", pb); pt.start(); return pt; } + public static String[] concat(String[] a, String[] b) { + if (a == null) { + return b; + } + if (b == null) { + return a; + } + int aLen = a.length; + int bLen = b.length; + String[] c = new String[aLen + bLen]; + System.arraycopy(a, 0, c, 0, aLen); + System.arraycopy(b, 0, c, aLen, bLen); + return c; + } + /** * Will stop the running Application. * First tries to shutdown nicely by connecting to the shut down port. diff --git a/test/com/sun/tools/attach/TempDirTest.java b/test/com/sun/tools/attach/TempDirTest.java new file mode 100644 --- /dev/null +++ b/test/com/sun/tools/attach/TempDirTest.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2014 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 com.sun.tools.attach.*; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Properties; +import java.util.List; +import java.io.File; + +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.ProcessThread; + +/* + * @test + * @bug 8033104 + * @summary Test to make sure attach and jvmstat works correctly when java.io.tmpdir is set + * @library /lib/testlibrary + * @run build Application Shutdown RunnerUtil + * @run main/timeout=10 TempDirTest + */ + +public class TempDirTest { + + public static void main(String args[]) throws Throwable { + + Path clientTmpDir = Files.createTempDirectory("TempDirTest-client"); + clientTmpDir.toFile().deleteOnExit(); + Path targetTmpDir = Files.createTempDirectory("TempDirTest-target"); + targetTmpDir.toFile().deleteOnExit(); + + // run the test with all possible combinations of setting java.io.tmpdir + runExperiment(null, null); + runExperiment(clientTmpDir, null); + runExperiment(clientTmpDir, targetTmpDir); + runExperiment(null, targetTmpDir); + + } + + private static int counter = 0; + + /* + * The actual test is in the nested class TestMain. + * The responsibility of this class is to: + * 1. Start the Application class in a separate process. + * 2. Find the pid and shutdown port of the running Application. + * 3. Launches the tests in nested class TestMain that will attach to the Application. + * 4. Shut down the Application. + */ + public static void runExperiment(Path clientTmpDir, Path targetTmpDir) throws Throwable { + + System.out.print("### Running tests with overridden tmpdir for"); + System.out.print(" client: " + (clientTmpDir == null ? "no" : "yes")); + System.out.print(" target: " + (targetTmpDir == null ? "no" : "yes")); + System.out.println(" ###"); + + final String pidFile = "TempDirTest.Application.pid-" + counter++; + ProcessThread processThread = null; + RunnerUtil.ProcessInfo info = null; + try { + String[] tmpDirArg = null; + if (targetTmpDir != null) { + tmpDirArg = new String[] {"-Djava.io.tmpdir=" + targetTmpDir}; + } + processThread = RunnerUtil.startApplication(pidFile, tmpDirArg); + info = RunnerUtil.readProcessInfo(pidFile); + launchTests(info.pid, clientTmpDir); + } catch (Throwable t) { + System.out.println("TempDirTest got unexpected exception: " + t); + t.printStackTrace(); + throw t; + } finally { + // Make sure the Application process is stopped. + RunnerUtil.stopApplication(info.shutdownPort, processThread); + } + } + + /** + * Runs the actual tests in nested class TestMain. + * The reason for running the tests in a separate process + * is that we need to modify the class path and + * the -Djava.io.tmpdir property. + */ + private static void launchTests(int pid, Path clientTmpDir) throws Throwable { + final String sep = File.separator; + + // Need to add jdk/lib/tools.jar to classpath. + String classpath = + System.getProperty("test.class.path", "") + File.pathSeparator + + System.getProperty("test.jdk", ".") + sep + "lib" + sep + "tools.jar"; + + String[] tmpDirArg = null; + if (clientTmpDir != null) { + tmpDirArg = new String [] {"-Djava.io.tmpdir=" + clientTmpDir}; + } + + // Arguments : [-Djava.io.tmpdir=] -classpath cp TempDirTest$TestMain pid + String[] args = RunnerUtil.concat( + tmpDirArg, + new String[] { + "-classpath", + classpath, + "TempDirTest$TestMain", + Integer.toString(pid) }); + OutputAnalyzer output = ProcessTools.executeTestJvm(args); + output.shouldHaveExitValue(0); + } + + /** + * This is the actual test. It will attach to the running Application + * and perform a number of basic attach tests. + */ + public static class TestMain { + public static void main(String args[]) throws Exception { + String pid = args[0]; + + // Test 1 - list method should list the target VM + System.out.println(" - Test: VirtualMachine.list"); + List l = VirtualMachine.list(); + boolean found = false; + for (VirtualMachineDescriptor vmd: l) { + if (vmd.id().equals(pid)) { + found = true; + break; + } + } + if (found) { + System.out.println(" - " + pid + " found."); + } else { + throw new RuntimeException(pid + " not found in VM list"); + } + + // Test 2 - try to attach and verify connection + + System.out.println(" - Attaching to application ..."); + VirtualMachine vm = VirtualMachine.attach(pid); + + System.out.println(" - Test: system properties in target VM"); + Properties props = vm.getSystemProperties(); + String value = props.getProperty("attach.test"); + if (value == null || !value.equals("true")) { + throw new RuntimeException("attach.test property not set"); + } + System.out.println(" - attach.test property set as expected"); + } + } +} diff --git a/test/com/sun/tools/attach/java.policy.allow b/test/com/sun/tools/attach/java.policy.allow --- a/test/com/sun/tools/attach/java.policy.allow +++ b/test/com/sun/tools/attach/java.policy.allow @@ -13,7 +13,6 @@ permission java.lang.RuntimePermission "accessClassInPackage.sun.jvmstat.monitor"; permission java.lang.RuntimePermission "loadLibrary.attach"; permission java.util.PropertyPermission "sun.jvmstat.*", "read"; - permission java.util.PropertyPermission "java.io.tmpdir", "read"; /* to read configuration file in META-INF/services, and write/delete .attach_pid */ permission java.io.FilePermission "<>", "read,write,delete"; diff --git a/test/com/sun/tools/attach/java.policy.deny b/test/com/sun/tools/attach/java.policy.deny --- a/test/com/sun/tools/attach/java.policy.deny +++ b/test/com/sun/tools/attach/java.policy.deny @@ -11,7 +11,6 @@ permission java.lang.RuntimePermission "accessClassInPackage.sun.tools.attach"; permission java.lang.RuntimePermission "loadLibrary.attach"; permission java.util.PropertyPermission "sun.jvmstat.*", "read"; - permission java.util.PropertyPermission "java.io.tmpdir", "read"; /* to read configuration file in META-INF/services, and write/delete .attach_pid */ permission java.io.FilePermission "<>", "read,write,delete";