--- a/jdk/make/java/java/FILES_java.gmk Mon Sep 14 18:45:20 2009 -0600
+++ b/jdk/make/java/java/FILES_java.gmk Mon Sep 14 18:54:26 2009 -0600
@@ -454,6 +454,8 @@
sun/misc/JavaLangAccess.java \
sun/misc/JavaIOAccess.java \
sun/misc/JavaIOFileDescriptorAccess.java \
- sun/misc/JavaNioAccess.java
+ sun/misc/JavaNioAccess.java \
+ sun/misc/Perf.java \
+ sun/misc/PerfCounter.java
FILES_java = $(JAVA_JAVA_java)
--- a/jdk/src/share/bin/parse_manifest.c Mon Sep 14 18:45:20 2009 -0600
+++ b/jdk/src/share/bin/parse_manifest.c Mon Sep 14 18:54:26 2009 -0600
@@ -59,7 +59,7 @@
char *out;
z_stream zs;
- if (entry->csize == 0xffffffff || entry->isize == 0xffffffff)
+ if (entry->csize == (size_t) -1 || entry->isize == (size_t) -1 )
return (NULL);
if (lseek(fd, entry->offset, SEEK_SET) < (off_t)0)
return (NULL);
--- a/jdk/src/share/classes/java/lang/ClassLoader.java Mon Sep 14 18:45:20 2009 -0600
+++ b/jdk/src/share/classes/java/lang/ClassLoader.java Mon Sep 14 18:54:26 2009 -0600
@@ -380,6 +380,7 @@
// First, check if the class has already been loaded
Class c = findLoadedClass(name);
if (c == null) {
+ long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
@@ -394,7 +395,13 @@
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
+ long t1 = System.nanoTime();
c = findClass(name);
+
+ // this is the defining class loader; record the stats
+ sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
+ sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
+ sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
--- a/jdk/src/share/classes/java/net/URLClassLoader.java Mon Sep 14 18:45:20 2009 -0600
+++ b/jdk/src/share/classes/java/net/URLClassLoader.java Mon Sep 14 18:54:26 2009 -0600
@@ -340,6 +340,7 @@
* used.
*/
private Class defineClass(String name, Resource res) throws IOException {
+ long t0 = System.nanoTime();
int i = name.lastIndexOf('.');
URL url = res.getCodeSourceURL();
if (i != -1) {
@@ -370,12 +371,14 @@
// Use (direct) ByteBuffer:
CodeSigner[] signers = res.getCodeSigners();
CodeSource cs = new CodeSource(url, signers);
+ sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0);
return defineClass(name, bb, cs);
} else {
byte[] b = res.getBytes();
// must read certificates AFTER reading bytes.
CodeSigner[] signers = res.getCodeSigners();
CodeSource cs = new CodeSource(url, signers);
+ sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0);
return defineClass(name, b, 0, b.length, cs);
}
}
--- a/jdk/src/share/classes/java/util/zip/ZipFile.java Mon Sep 14 18:45:20 2009 -0600
+++ b/jdk/src/share/classes/java/util/zip/ZipFile.java Mon Sep 14 18:54:26 2009 -0600
@@ -195,7 +195,10 @@
if (charset == null)
throw new NullPointerException("charset is null");
this.zc = ZipCoder.get(charset);
+ long t0 = System.nanoTime();
jzfile = open(name, mode, file.lastModified());
+ sun.misc.PerfCounter.getZipFileOpenTime().addElapsedTimeFrom(t0);
+ sun.misc.PerfCounter.getZipFileCount().increment();
this.name = name;
this.total = getTotal(jzfile);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/misc/PerfCounter.java Mon Sep 14 18:54:26 2009 -0600
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.misc;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.LongBuffer;
+import java.security.AccessController;
+
+/**
+ * Performance counter support for internal JRE classes.
+ * This class defines a fixed list of counters for the platform
+ * to use as an interim solution until RFE# 6209222 is implemented.
+ * The perf counters will be created in the jvmstat perf buffer
+ * that the HotSpot VM creates. The default size is 32K and thus
+ * the number of counters is bounded. You can alter the size
+ * with -XX:PerfDataMemorySize=<bytes> option. If there is
+ * insufficient memory in the jvmstat perf buffer, the C heap memory
+ * will be used and thus the application will continue to run if
+ * the counters added exceeds the buffer size but the counters
+ * will be missing.
+ *
+ * See HotSpot jvmstat implementation for certain circumstances
+ * that the jvmstat perf buffer is not supported.
+ *
+ */
+public class PerfCounter {
+ private static final Perf perf =
+ AccessController.doPrivileged(new Perf.GetPerfAction());
+
+ // Must match values defined in hotspot/src/share/vm/runtime/perfdata.hpp
+ private final static int V_Constant = 1;
+ private final static int V_Monotonic = 2;
+ private final static int V_Variable = 3;
+ private final static int U_None = 1;
+
+ private final String name;
+ private final LongBuffer lb;
+
+ private PerfCounter(String name, int type) {
+ this.name = name;
+ ByteBuffer bb = perf.createLong(name, U_None, type, 0L);
+ bb.order(ByteOrder.nativeOrder());
+ this.lb = bb.asLongBuffer();
+ }
+
+ static PerfCounter newPerfCounter(String name) {
+ return new PerfCounter(name, V_Variable);
+ }
+
+ static PerfCounter newConstantPerfCounter(String name) {
+ PerfCounter c = new PerfCounter(name, V_Constant);
+ return c;
+ }
+
+ /**
+ * Returns the current value of the perf counter.
+ */
+ public synchronized long get() {
+ return lb.get(0);
+ }
+
+ /**
+ * Sets the value of the perf counter to the given newValue.
+ */
+ public synchronized void set(long newValue) {
+ lb.put(0, newValue);
+ }
+
+ /**
+ * Adds the given value to the perf counter.
+ */
+ public synchronized void add(long value) {
+ long res = get() + value;
+ lb.put(0, res);
+ }
+
+ /**
+ * Increments the perf counter with 1.
+ */
+ public void increment() {
+ add(1);
+ }
+
+ /**
+ * Adds the given interval to the perf counter.
+ */
+ public void addTime(long interval) {
+ add(interval);
+ }
+
+ /**
+ * Adds the elapsed time from the given start time (ns) to the perf counter.
+ */
+ public void addElapsedTimeFrom(long startTime) {
+ add(System.nanoTime() - startTime);
+ }
+
+ @Override
+ public String toString() {
+ return name + " = " + get();
+ }
+
+ static class CoreCounters {
+ static final PerfCounter pdt = newPerfCounter("sun.classloader.parentDelegationTime");
+ static final PerfCounter lc = newPerfCounter("sun.classloader.findClasses");
+ static final PerfCounter lct = newPerfCounter("sun.classloader.findClassTime");
+ static final PerfCounter rcbt = newPerfCounter("sun.urlClassLoader.readClassBytesTime");
+ static final PerfCounter zfc = newPerfCounter("sun.zip.zipFiles");
+ static final PerfCounter zfot = newPerfCounter("sun.zip.zipFile.openTime");
+ }
+
+ static class WindowsClientCounters {
+ static final PerfCounter d3dAvailable = newConstantPerfCounter("sun.java2d.d3d.available");
+ }
+
+ /**
+ * Number of findClass calls
+ */
+ public static PerfCounter getFindClasses() {
+ return CoreCounters.lc;
+ }
+
+ /**
+ * Time (ns) spent in finding classes that includes
+ * lookup and read class bytes and defineClass
+ */
+ public static PerfCounter getFindClassTime() {
+ return CoreCounters.lct;
+ }
+
+ /**
+ * Time (ns) spent in finding classes
+ */
+ public static PerfCounter getReadClassBytesTime() {
+ return CoreCounters.rcbt;
+ }
+
+ /**
+ * Time (ns) spent in the parent delegation to
+ * the parent of the defining class loader
+ */
+ public static PerfCounter getParentDelegationTime() {
+ return CoreCounters.pdt;
+ }
+
+ /**
+ * Number of zip files opened.
+ */
+ public static PerfCounter getZipFileCount() {
+ return CoreCounters.zfc;
+ }
+
+ /**
+ * Time (ns) spent in opening the zip files that
+ * includes building the entries hash table
+ */
+ public static PerfCounter getZipFileOpenTime() {
+ return CoreCounters.zfot;
+ }
+
+ /**
+ * D3D graphic pipeline available
+ */
+ public static PerfCounter getD3DAvailable() {
+ return WindowsClientCounters.d3dAvailable;
+ }
+}
--- a/jdk/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java Mon Sep 14 18:45:20 2009 -0600
+++ b/jdk/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java Mon Sep 14 18:54:26 2009 -0600
@@ -67,6 +67,9 @@
if (d3dAvailable) {
// we don't use pixel formats for the d3d pipeline
pfDisabled = true;
+ sun.misc.PerfCounter.getD3DAvailable().set(1);
+ } else {
+ sun.misc.PerfCounter.getD3DAvailable().set(0);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/6842838/CreateBadJar.java Mon Sep 14 18:54:26 2009 -0600
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * Borrowing significantly from Martin Buchholz's CorruptedZipFiles.java
+ *
+ * Needed a way of testing the checks for corrupt zip/jar entry in
+ * inflate_file from file j2se/src/share/bin/parse_manifest.c
+ * and running them with the 64-bit launcher. e.g.
+ * sparcv9/bin/java -jar badjar.jar
+ *
+ * Run from a script driver Test6842838.sh as we want to specifically run
+ * bin/sparcv9/java, the 64-bit launcher.
+ *
+ * So this program will create a zip file and damage it in the way
+ * required to tickle this bug.
+ *
+ * It will cause a buffer overrun: but that will not always crash.
+ * Use libumem preloaded by the script driver in order to
+ * abort quickly when the overrun happens. That makes the test
+ * Solaris-specific.
+ */
+
+import java.util.*;
+import java.util.zip.*;
+import java.io.*;
+import static java.lang.System.*;
+import static java.util.zip.ZipFile.*;
+
+public class CreateBadJar {
+
+public static void main(String [] arguments) {
+
+ if (arguments.length != 2) {
+ throw new RuntimeException("Arguments: jarfilename entryname");
+ }
+ String outFile = arguments[0];
+ String entryName = arguments[1];
+
+ try {
+ // If the named file doesn't exist, create it.
+ // If it does, we are expecting it to contain the named entry, for
+ // alteration.
+ if (!new File(outFile).exists()) {
+ System.out.println("Creating file " + outFile);
+
+ // Create the requested zip/jar file.
+ ZipOutputStream zos = null;
+ zos = new ZipOutputStream(
+ new FileOutputStream(outFile));
+
+ ZipEntry e = new ZipEntry(entryName);
+ zos.putNextEntry(e);
+ for (int j=0; j<50000; j++) {
+ zos.write((int)'a');
+ }
+ zos.closeEntry();
+ zos.close();
+ zos = null;
+ }
+
+ // Read it.
+ int len = (int)(new File(outFile).length());
+ byte[] good = new byte[len];
+ FileInputStream fis = new FileInputStream(outFile);
+ fis.read(good);
+ fis.close();
+ fis = null;
+
+ int endpos = len - ENDHDR;
+ int cenpos = u16(good, endpos+ENDOFF);
+ if (u32(good, cenpos) != CENSIG) throw new RuntimeException("Where's CENSIG?");
+
+ byte[] bad;
+ bad = good.clone();
+
+ // Corrupt it...
+ int pos = findInCEN(bad, cenpos, entryName);
+
+ // What bad stuff are we doing to it?
+ // Store a 32-bit -1 in uncomp size.
+ bad[pos+0x18]=(byte)0xff;
+ bad[pos+0x19]=(byte)0xff;
+ bad[pos+0x1a]=(byte)0xff;
+ bad[pos+0x1b]=(byte)0xff;
+
+ // Bad work complete, delete the original.
+ new File(outFile).delete();
+
+ // Write it.
+ FileOutputStream fos = new FileOutputStream(outFile);
+ fos.write(bad);
+ fos.close();
+ fos = null;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+}
+
+ /*
+ * Scan Central Directory File Headers looking for the named entry.
+ */
+
+ static int findInCEN(byte[] bytes, int cenpos, String entryName) {
+ int pos = cenpos;
+ int nextPos = 0;
+ String filename = null;
+ do {
+ if (nextPos != 0) {
+ pos = nextPos;
+ }
+ System.out.println("entry at pos = " + pos);
+ if (u32(bytes, pos) != CENSIG) throw new RuntimeException ("entry not found in CEN or premature end...");
+
+ int csize = u32(bytes, pos+0x14); // +0x14 1 dword csize
+ int uncompsize = u32(bytes, pos+0x18); // +0x18 1 dword uncomp size
+ int filenameLength = u16(bytes, pos+0x1c); // +0x1c 1 word length of filename
+ int extraLength = u16(bytes, pos+0x1e); // +0x1e 1 world length of extra field
+ int commentLength = u16(bytes, pos+0x20); // +0x20 1 world length of file comment
+ filename = new String(bytes, pos+0x2e, filenameLength); // +0x2e chars of filename
+ int offset = u32(bytes, pos+0x2a); // +0x2a chars of filename
+
+ System.out.println("filename = " + filename + "\ncsize = " + csize +
+ " uncomp.size = " + uncompsize +" file offset = " + offset);
+ nextPos = pos + 0x2e + filenameLength + extraLength + commentLength;
+
+ } while (!filename.equals(entryName));
+
+ System.out.println("entry found at pos = " + pos);
+ return pos;
+ }
+
+ static int u8(byte[] data, int offset) {
+ return data[offset]&0xff;
+ }
+
+ static int u16(byte[] data, int offset) {
+ return u8(data,offset) + (u8(data,offset+1)<<8);
+ }
+
+ static int u32(byte[] data, int offset) {
+ return u16(data,offset) + (u16(data,offset+2)<<16);
+ }
+
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/6842838/Test6842838.sh Mon Sep 14 18:54:26 2009 -0600
@@ -0,0 +1,75 @@
+#!/bin/sh -x
+
+#
+# @test @(#)Test6842838.sh
+# @bug 6842838
+# @summary Test 6842838 64-bit launcher failure due to corrupt jar
+# @run shell Test6842838.sh
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+if [ "${TESTSRC}" = "" ]
+then TESTSRC=.
+fi
+
+if [ "${TESTJAVA}" = "" ]
+then
+ PARENT=`dirname \`which java\``
+ TESTJAVA=`dirname ${PARENT}`
+ echo "TESTJAVA not set, selecting " ${TESTJAVA}
+ echo "If this is incorrect, try setting the variable manually."
+fi
+
+if [ "${TESTCLASSES}" = "" ]
+then
+ echo "TESTCLASSES not set. Test cannot execute. Failed."
+ exit 1
+fi
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+ SunOS )
+ NULL=/dev/null
+ PS=":"
+ FS="/"
+ JAVA_EXE=${TESTJAVA}${FS}bin${FS}sparcv9${FS}java
+ ;;
+ * )
+ echo "Only testing on sparcv9 (use libumem to reliably catch buffer overrun)"
+ exit 0;
+ ;;
+esac
+
+BADFILE=newbadjar.jar
+
+${JAVA_EXE} -version
+rm -f ${BADFILE}
+${TESTJAVA}/bin/javac CreateBadJar.java
+${JAVA_EXE} CreateBadJar ${BADFILE} "META-INF/MANIFEST.MF"
+LD_PRELOAD=/lib/64/libumem.so ${JAVA_EXE} -jar ${BADFILE} > test.out 2>&1
+
+grep "Invalid or corrupt jarfile" test.out
+exit $?