Merge
authordcubed
Mon, 14 Sep 2009 18:54:26 -0600
changeset 3852 cdde5edc78ff
parent 3851 42033ba29ec8 (current diff)
parent 3850 4932fc1ba4cd (diff)
child 3853 9d2382b74894
Merge
--- 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 $?