# HG changeset patch # User tamao # Date 1372889093 25200 # Node ID 70bea4a43c6d5a8ef43aa61255f48d93ceae949d # Parent 536976a22f5fb275571a4f5a24f5d7375e9be493# Parent cedf20e2a655329f04732f2e67ebbb98cf46cb07 Merge diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/CLHSDB.java --- a/agent/src/share/classes/sun/jvm/hotspot/CLHSDB.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/CLHSDB.java Wed Jul 03 15:04:53 2013 -0700 @@ -31,13 +31,19 @@ import java.util.*; public class CLHSDB { + + public CLHSDB(JVMDebugger d) { + jvmDebugger = d; + } + public static void main(String[] args) { new CLHSDB(args).run(); } - private void run() { - // At this point, if pidText != null we are supposed to attach to it. - // Else, if execPath != null, it is the path of a jdk/bin/java + public void run() { + // If jvmDebugger is already set, we have been given a JVMDebugger. + // Otherwise, if pidText != null we are supposed to attach to it. + // Finally, if execPath != null, it is the path of a jdk/bin/java // and coreFilename is the pathname of a core file we are // supposed to attach to. @@ -49,7 +55,9 @@ } }); - if (pidText != null) { + if (jvmDebugger != null) { + attachDebugger(jvmDebugger); + } else if (pidText != null) { attachDebugger(pidText); } else if (execPath != null) { attachDebugger(execPath, coreFilename); @@ -96,6 +104,7 @@ // Internals only below this point // private HotSpotAgent agent; + private JVMDebugger jvmDebugger; private boolean attached; // These had to be made data members because they are referenced in inner classes. private String pidText; @@ -120,7 +129,7 @@ case (1): if (args[0].equals("help") || args[0].equals("-help")) { doUsage(); - System.exit(0); + return; } // If all numbers, it is a PID to attach to // Else, it is a pathname to a .../bin/java for a core file. @@ -142,10 +151,15 @@ default: System.out.println("HSDB Error: Too many options specified"); doUsage(); - System.exit(1); + return; } } + private void attachDebugger(JVMDebugger d) { + agent.attach(d); + attached = true; + } + /** NOTE we are in a different thread here than either the main thread or the Swing/AWT event handler thread, so we must be very careful when creating or removing widgets */ diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java --- a/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java Wed Jul 03 15:04:53 2013 -0700 @@ -101,6 +101,9 @@ import sun.jvm.hotspot.utilities.soql.JSJavaScriptEngine; public class CommandProcessor { + + volatile boolean quit; + public abstract static class DebuggerInterface { public abstract HotSpotAgent getAgent(); public abstract boolean isAttached(); @@ -1135,7 +1138,7 @@ usage(); } else { debugger.detach(); - System.exit(0); + quit = true; } } }, @@ -1714,7 +1717,7 @@ } protected void quit() { debugger.detach(); - System.exit(0); + quit = true; } protected BufferedReader getInputReader() { return in; @@ -1781,7 +1784,7 @@ public void run(boolean prompt) { // Process interactive commands. - while (true) { + while (!quit) { if (prompt) printPrompt(); String ln = null; try { diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/HSDB.java --- a/agent/src/share/classes/sun/jvm/hotspot/HSDB.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/HSDB.java Wed Jul 03 15:04:53 2013 -0700 @@ -59,8 +59,11 @@ // Internals only below this point // private HotSpotAgent agent; + private JVMDebugger jvmDebugger; private JDesktopPane desktop; private boolean attached; + private boolean argError; + private JFrame frame; /** List */ private java.util.List attachMenuItems; /** List */ @@ -85,6 +88,11 @@ System.out.println(" path-to-corefile: Debug this corefile. The default is 'core'"); System.out.println(" If no arguments are specified, you can select what to do from the GUI.\n"); HotSpotAgent.showUsage(); + argError = true; + } + + public HSDB(JVMDebugger d) { + jvmDebugger = d; } private HSDB(String[] args) { @@ -95,7 +103,6 @@ case (1): if (args[0].equals("help") || args[0].equals("-help")) { doUsage(); - System.exit(0); } // If all numbers, it is a PID to attach to // Else, it is a pathname to a .../bin/java for a core file. @@ -117,24 +124,29 @@ default: System.out.println("HSDB Error: Too many options specified"); doUsage(); - System.exit(1); } } - private void run() { - // At this point, if pidText != null we are supposed to attach to it. - // Else, if execPath != null, it is the path of a jdk/bin/java - // and coreFilename is the pathname of a core file we are - // supposed to attach to. + // close this tool without calling System.exit + protected void closeUI() { + workerThread.shutdown(); + frame.dispose(); + } + + public void run() { + // Don't start the UI if there were bad arguments. + if (argError) { + return; + } agent = new HotSpotAgent(); workerThread = new WorkerThread(); attachMenuItems = new java.util.ArrayList(); detachMenuItems = new java.util.ArrayList(); - JFrame frame = new JFrame("HSDB - HotSpot Debugger"); + frame = new JFrame("HSDB - HotSpot Debugger"); frame.setSize(800, 600); - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); JMenuBar menuBar = new JMenuBar(); @@ -197,7 +209,7 @@ item = createMenuItem("Exit", new ActionListener() { public void actionPerformed(ActionEvent e) { - System.exit(0); + closeUI(); } }); item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.ALT_MASK)); @@ -406,7 +418,15 @@ } }); - if (pidText != null) { + // If jvmDebugger is already set, we have been given a JVMDebugger. + // Otherwise, if pidText != null we are supposed to attach to it. + // Finally, if execPath != null, it is the path of a jdk/bin/java + // and coreFilename is the pathname of a core file we are + // supposed to attach to. + + if (jvmDebugger != null) { + attach(jvmDebugger); + } else if (pidText != null) { attach(pidText); } else if (execPath != null) { attach(execPath, coreFilename); @@ -1113,6 +1133,12 @@ }); } + // Attach to existing JVMDebugger, which should be already attached to a core/process. + private void attach(JVMDebugger d) { + attached = true; + showThreadsDialog(); + } + /** NOTE we are in a different thread here than either the main thread or the Swing/AWT event handler thread, so we must be very careful when creating or removing widgets */ diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java --- a/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java Wed Jul 03 15:04:53 2013 -0700 @@ -25,6 +25,8 @@ package sun.jvm.hotspot; import java.rmi.RemoteException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import sun.jvm.hotspot.debugger.Debugger; import sun.jvm.hotspot.debugger.DebuggerException; @@ -63,7 +65,6 @@ private String os; private String cpu; - private String fileSep; // The system can work in several ways: // - Attaching to local process @@ -155,6 +156,14 @@ go(); } + /** This uses a JVMDebugger that is already attached to the core or process */ + public synchronized void attach(JVMDebugger d) + throws DebuggerException { + debugger = d; + isServer = false; + go(); + } + /** This attaches to a "debug server" on a remote machine; this remote server has already attached to a process or opened a core file and is waiting for RMI calls on the Debugger object to @@ -303,28 +312,37 @@ // server, but not client attaching to server) // - try { - os = PlatformInfo.getOS(); - cpu = PlatformInfo.getCPU(); - } - catch (UnsupportedPlatformException e) { - throw new DebuggerException(e); - } - fileSep = System.getProperty("file.separator"); + // Handle existing or alternate JVMDebugger: + // these will set os, cpu independently of our PlatformInfo implementation. + String alternateDebugger = System.getProperty("sa.altDebugger"); + if (debugger != null) { + setupDebuggerExisting(); + + } else if (alternateDebugger != null) { + setupDebuggerAlternate(alternateDebugger); - if (os.equals("solaris")) { - setupDebuggerSolaris(); - } else if (os.equals("win32")) { - setupDebuggerWin32(); - } else if (os.equals("linux")) { - setupDebuggerLinux(); - } else if (os.equals("bsd")) { - setupDebuggerBsd(); - } else if (os.equals("darwin")) { - setupDebuggerDarwin(); } else { - // Add support for more operating systems here - throw new DebuggerException("Operating system " + os + " not yet supported"); + // Otherwise, os, cpu are those of our current platform: + try { + os = PlatformInfo.getOS(); + cpu = PlatformInfo.getCPU(); + } catch (UnsupportedPlatformException e) { + throw new DebuggerException(e); + } + if (os.equals("solaris")) { + setupDebuggerSolaris(); + } else if (os.equals("win32")) { + setupDebuggerWin32(); + } else if (os.equals("linux")) { + setupDebuggerLinux(); + } else if (os.equals("bsd")) { + setupDebuggerBsd(); + } else if (os.equals("darwin")) { + setupDebuggerDarwin(); + } else { + // Add support for more operating systems here + throw new DebuggerException("Operating system " + os + " not yet supported"); + } } if (isServer) { @@ -423,6 +441,41 @@ // OS-specific debugger setup/connect routines // + // Use the existing JVMDebugger, as passed to our constructor. + // Retrieve os and cpu from that debugger, not the current platform. + private void setupDebuggerExisting() { + + os = debugger.getOS(); + cpu = debugger.getCPU(); + setupJVMLibNames(os); + machDesc = debugger.getMachineDescription(); + } + + // Given a classname, load an alternate implementation of JVMDebugger. + private void setupDebuggerAlternate(String alternateName) { + + try { + Class c = Class.forName(alternateName); + Constructor cons = c.getConstructor(); + debugger = (JVMDebugger) cons.newInstance(); + attachDebugger(); + setupDebuggerExisting(); + + } catch (ClassNotFoundException cnfe) { + throw new DebuggerException("Cannot find alternate SA Debugger: '" + alternateName + "'"); + } catch (NoSuchMethodException nsme) { + throw new DebuggerException("Alternate SA Debugger: '" + alternateName + "' has missing constructor."); + } catch (InstantiationException ie) { + throw new DebuggerException("Alternate SA Debugger: '" + alternateName + "' fails to initialise: ", ie); + } catch (IllegalAccessException iae) { + throw new DebuggerException("Alternate SA Debugger: '" + alternateName + "' fails to initialise: ", iae); + } catch (InvocationTargetException iae) { + throw new DebuggerException("Alternate SA Debugger: '" + alternateName + "' fails to initialise: ", iae); + } + + System.err.println("Loaded alternate HotSpot SA Debugger: " + alternateName); + } + // // Solaris // @@ -466,6 +519,11 @@ debugger = new RemoteDebuggerClient(remote); machDesc = ((RemoteDebuggerClient) debugger).getMachineDescription(); os = debugger.getOS(); + setupJVMLibNames(os); + cpu = debugger.getCPU(); + } + + private void setupJVMLibNames(String os) { if (os.equals("solaris")) { setupJVMLibNamesSolaris(); } else if (os.equals("win32")) { @@ -479,8 +537,6 @@ } else { throw new RuntimeException("Unknown OS type"); } - - cpu = debugger.getCPU(); } private void setupJVMLibNamesSolaris() { diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxAddress.java --- a/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxAddress.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxAddress.java Wed Jul 03 15:04:53 2013 -0700 @@ -26,11 +26,11 @@ import sun.jvm.hotspot.debugger.*; -class LinuxAddress implements Address { +public class LinuxAddress implements Address { protected LinuxDebugger debugger; protected long addr; - LinuxAddress(LinuxDebugger debugger, long addr) { + public LinuxAddress(LinuxDebugger debugger, long addr) { this.debugger = debugger; this.addr = addr; } diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxOopHandle.java --- a/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxOopHandle.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxOopHandle.java Wed Jul 03 15:04:53 2013 -0700 @@ -26,8 +26,8 @@ import sun.jvm.hotspot.debugger.*; -class LinuxOopHandle extends LinuxAddress implements OopHandle { - LinuxOopHandle(LinuxDebugger debugger, long addr) { +public class LinuxOopHandle extends LinuxAddress implements OopHandle { + public LinuxOopHandle(LinuxDebugger debugger, long addr) { super(debugger, addr); } diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Wed Jul 03 15:04:53 2013 -0700 @@ -246,7 +246,7 @@ } } - private static final boolean disableDerivedPrinterTableCheck; + private static final boolean disableDerivedPointerTableCheck; private static final Properties saProps; static { @@ -256,12 +256,12 @@ url = VM.class.getClassLoader().getResource("sa.properties"); saProps.load(new BufferedInputStream(url.openStream())); } catch (Exception e) { - throw new RuntimeException("Unable to load properties " + + System.err.println("Unable to load properties " + (url == null ? "null" : url.toString()) + ": " + e.getMessage()); } - disableDerivedPrinterTableCheck = System.getProperty("sun.jvm.hotspot.runtime.VM.disableDerivedPointerTableCheck") != null; + disableDerivedPointerTableCheck = System.getProperty("sun.jvm.hotspot.runtime.VM.disableDerivedPointerTableCheck") != null; } private VM(TypeDataBase db, JVMDebugger debugger, boolean isBigEndian) { @@ -371,7 +371,8 @@ /** This is used by the debugging system */ public static void initialize(TypeDataBase db, JVMDebugger debugger) { if (soleInstance != null) { - throw new RuntimeException("Attempt to initialize VM twice"); + // Using multiple SA Tool classes in the same process creates a call here. + return; } soleInstance = new VM(db, debugger, debugger.getMachineDescription().isBigEndian()); @@ -683,7 +684,7 @@ /** Returns true if C2 derived pointer table should be used, false otherwise */ public boolean useDerivedPointerTable() { - return !disableDerivedPrinterTableCheck; + return !disableDerivedPointerTableCheck; } /** Returns the code cache; should not be used if is core build */ diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java Wed Jul 03 15:04:53 2013 -0700 @@ -41,6 +41,14 @@ public class ClassLoaderStats extends Tool { boolean verbose = true; + public ClassLoaderStats() { + super(); + } + + public ClassLoaderStats(JVMDebugger d) { + super(d); + } + public static void main(String[] args) { ClassLoaderStats cls = new ClassLoaderStats(); cls.start(args); diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/tools/FinalizerInfo.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/FinalizerInfo.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/FinalizerInfo.java Wed Jul 03 15:04:53 2013 -0700 @@ -24,6 +24,7 @@ package sun.jvm.hotspot.tools; +import sun.jvm.hotspot.debugger.JVMDebugger; import sun.jvm.hotspot.tools.*; import sun.jvm.hotspot.oops.*; @@ -42,6 +43,15 @@ * summary of these objects in the form of a histogram. */ public class FinalizerInfo extends Tool { + + public FinalizerInfo() { + super(); + } + + public FinalizerInfo(JVMDebugger d) { + super(d); + } + public static void main(String[] args) { FinalizerInfo finfo = new FinalizerInfo(); finfo.start(args); diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/tools/FlagDumper.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/FlagDumper.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/FlagDumper.java Wed Jul 03 15:04:53 2013 -0700 @@ -25,10 +25,19 @@ package sun.jvm.hotspot.tools; import java.io.PrintStream; +import sun.jvm.hotspot.debugger.JVMDebugger; import sun.jvm.hotspot.runtime.*; public class FlagDumper extends Tool { + public FlagDumper() { + super(); + } + + public FlagDumper(JVMDebugger d) { + super(d); + } + public void run() { VM.Flag[] flags = VM.getVM().getCommandLineFlags(); PrintStream out = System.out; diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/tools/HeapDumper.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/HeapDumper.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/HeapDumper.java Wed Jul 03 15:04:53 2013 -0700 @@ -25,6 +25,7 @@ package sun.jvm.hotspot.tools; import sun.jvm.hotspot.utilities.HeapHprofBinWriter; +import sun.jvm.hotspot.debugger.JVMDebugger; import java.io.IOException; /* @@ -42,6 +43,11 @@ this.dumpFile = dumpFile; } + public HeapDumper(String dumpFile, JVMDebugger d) { + super(d); + this.dumpFile = dumpFile; + } + protected void printFlagsUsage() { System.out.println(" \tto dump heap to " + DEFAULT_DUMP_FILE); diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java Wed Jul 03 15:04:53 2013 -0700 @@ -29,12 +29,21 @@ import sun.jvm.hotspot.gc_implementation.g1.*; import sun.jvm.hotspot.gc_implementation.parallelScavenge.*; import sun.jvm.hotspot.gc_implementation.shared.*; +import sun.jvm.hotspot.debugger.JVMDebugger; import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.runtime.*; public class HeapSummary extends Tool { + public HeapSummary() { + super(); + } + + public HeapSummary(JVMDebugger d) { + super(d); + } + public static void main(String[] args) { HeapSummary hs = new HeapSummary(); hs.start(args); diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/tools/JInfo.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/JInfo.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/JInfo.java Wed Jul 03 15:04:53 2013 -0700 @@ -25,12 +25,21 @@ package sun.jvm.hotspot.tools; import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.debugger.JVMDebugger; public class JInfo extends Tool { + public JInfo() { + super(); + } + public JInfo(int m) { mode = m; } + public JInfo(JVMDebugger d) { + super(d); + } + protected boolean needsJavaPrefix() { return false; } diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/tools/JMap.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/JMap.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/JMap.java Wed Jul 03 15:04:53 2013 -0700 @@ -25,6 +25,7 @@ package sun.jvm.hotspot.tools; import java.io.*; +import sun.jvm.hotspot.debugger.JVMDebugger; import sun.jvm.hotspot.utilities.*; public class JMap extends Tool { @@ -36,6 +37,10 @@ this(MODE_PMAP); } + public JMap(JVMDebugger d) { + super(d); + } + protected boolean needsJavaPrefix() { return false; } diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/tools/JSnap.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/JSnap.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/JSnap.java Wed Jul 03 15:04:53 2013 -0700 @@ -25,9 +25,19 @@ package sun.jvm.hotspot.tools; import java.io.*; +import sun.jvm.hotspot.debugger.JVMDebugger; import sun.jvm.hotspot.runtime.*; public class JSnap extends Tool { + + public JSnap() { + super(); + } + + public JSnap(JVMDebugger d) { + super(d); + } + public void run() { final PrintStream out = System.out; if (PerfMemory.initialized()) { diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/tools/JStack.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/JStack.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/JStack.java Wed Jul 03 15:04:53 2013 -0700 @@ -24,6 +24,8 @@ package sun.jvm.hotspot.tools; +import sun.jvm.hotspot.debugger.JVMDebugger; + public class JStack extends Tool { public JStack(boolean mixedMode, boolean concurrentLocks) { this.mixedMode = mixedMode; @@ -34,6 +36,10 @@ this(true, true); } + public JStack(JVMDebugger d) { + super(d); + } + protected boolean needsJavaPrefix() { return false; } diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/tools/ObjectHistogram.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/ObjectHistogram.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/ObjectHistogram.java Wed Jul 03 15:04:53 2013 -0700 @@ -33,6 +33,14 @@ an object histogram from a remote or crashed VM. */ public class ObjectHistogram extends Tool { + public ObjectHistogram() { + super(); + } + + public ObjectHistogram(JVMDebugger d) { + super(d); + } + public void run() { run(System.out, System.err); } diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/tools/PMap.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/PMap.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/PMap.java Wed Jul 03 15:04:53 2013 -0700 @@ -31,6 +31,15 @@ import sun.jvm.hotspot.runtime.*; public class PMap extends Tool { + + public PMap() { + super(); + } + + public PMap(JVMDebugger d) { + super(d); + } + public void run() { run(System.out); } diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/tools/PStack.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/PStack.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/PStack.java Wed Jul 03 15:04:53 2013 -0700 @@ -45,6 +45,10 @@ this(true, true); } + public PStack(JVMDebugger d) { + super(d); + } + public void run() { run(System.out); } diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/tools/StackTrace.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/StackTrace.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/StackTrace.java Wed Jul 03 15:04:53 2013 -0700 @@ -45,6 +45,16 @@ run(System.out); } + public StackTrace(JVMDebugger d) { + super(d); + } + + public StackTrace(JVMDebugger d, boolean v, boolean concurrentLocks) { + super(d); + this.verbose = v; + this.concurrentLocks = concurrentLocks; + } + public void run(java.io.PrintStream tty) { // Ready to go with the database... try { diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/tools/SysPropsDumper.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/SysPropsDumper.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/SysPropsDumper.java Wed Jul 03 15:04:53 2013 -0700 @@ -27,10 +27,19 @@ import java.io.PrintStream; import java.util.*; +import sun.jvm.hotspot.debugger.JVMDebugger; import sun.jvm.hotspot.runtime.*; public class SysPropsDumper extends Tool { + public SysPropsDumper() { + super(); + } + + public SysPropsDumper(JVMDebugger d) { + super(d); + } + public void run() { Properties sysProps = VM.getVM().getSystemProperties(); PrintStream out = System.out; diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/tools/Tool.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/Tool.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/Tool.java Wed Jul 03 15:04:53 2013 -0700 @@ -35,6 +35,7 @@ public abstract class Tool implements Runnable { private HotSpotAgent agent; + private JVMDebugger jvmDebugger; private int debugeeType; // debugeeType is one of constants below @@ -42,6 +43,13 @@ protected static final int DEBUGEE_CORE = 1; protected static final int DEBUGEE_REMOTE = 2; + public Tool() { + } + + public Tool(JVMDebugger d) { + jvmDebugger = d; + } + public String getName() { return getClass().getName(); } @@ -90,7 +98,6 @@ protected void usage() { printUsage(); - System.exit(1); } /* @@ -106,13 +113,13 @@ protected void stop() { if (agent != null) { agent.detach(); - System.exit(0); } } protected void start(String[] args) { if ((args.length < 1) || (args.length > 2)) { usage(); + return; } // Attempt to handle -h or -help or some invalid flag @@ -185,13 +192,31 @@ } if (e.getMessage() != null) { err.print(e.getMessage()); + e.printStackTrace(); } err.println(); - System.exit(1); + return; } err.println("Debugger attached successfully."); + startInternal(); + } + // When using an existing JVMDebugger. + public void start() { + + if (jvmDebugger == null) { + throw new RuntimeException("Tool.start() called with no JVMDebugger set."); + } + agent = new HotSpotAgent(); + agent.attach(jvmDebugger); + startInternal(); + } + + // Remains of the start mechanism, common to both start methods. + private void startInternal() { + + PrintStream err = System.err; VM vm = VM.getVM(); if (vm.isCore()) { err.println("Core build detected."); diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassDump.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassDump.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassDump.java Wed Jul 03 15:04:53 2013 -0700 @@ -25,6 +25,7 @@ package sun.jvm.hotspot.tools.jcore; import java.io.*; +import java.lang.reflect.Constructor; import java.util.jar.JarOutputStream; import java.util.jar.JarEntry; import java.util.jar.Manifest; @@ -38,6 +39,16 @@ private ClassFilter classFilter; private String outputDirectory; private JarOutputStream jarStream; + private String pkgList; + + public ClassDump() { + super(); + } + + public ClassDump(JVMDebugger d, String pkgList) { + super(d); + this.pkgList = pkgList; + } public void setClassFilter(ClassFilter cf) { classFilter = cf; @@ -63,6 +74,25 @@ public void run() { // Ready to go with the database... try { + // The name of the filter always comes from a System property. + // If we have a pkgList, pass it, otherwise let the filter read + // its own System property for the list of classes. + String filterClassName = System.getProperty("sun.jvm.hotspot.tools.jcore.filter", + "sun.jvm.hotspot.tools.jcore.PackageNameFilter"); + try { + Class filterClass = Class.forName(filterClassName); + if (pkgList == null) { + classFilter = (ClassFilter) filterClass.newInstance(); + } else { + Constructor con = filterClass.getConstructor(String.class); + classFilter = (ClassFilter) con.newInstance(pkgList); + } + } catch(Exception exp) { + System.err.println("Warning: Can not create class filter!"); + } + + String outputDirectory = System.getProperty("sun.jvm.hotspot.tools.jcore.outputDir", "."); + setOutputDirectory(outputDirectory); // walk through the system dictionary SystemDictionary dict = VM.getVM().getSystemDictionary(); @@ -139,26 +169,8 @@ } public static void main(String[] args) { - // load class filters - ClassFilter classFilter = null; - String filterClassName = System.getProperty("sun.jvm.hotspot.tools.jcore.filter"); - if (filterClassName != null) { - try { - Class filterClass = Class.forName(filterClassName); - classFilter = (ClassFilter) filterClass.newInstance(); - } catch(Exception exp) { - System.err.println("Warning: Can not create class filter!"); - } - } - - String outputDirectory = System.getProperty("sun.jvm.hotspot.tools.jcore.outputDir"); - if (outputDirectory == null) - outputDirectory = "."; - ClassDump cd = new ClassDump(); - cd.setClassFilter(classFilter); - cd.setOutputDirectory(outputDirectory); cd.start(args); cd.stop(); } diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/tools/soql/JSDB.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/soql/JSDB.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/soql/JSDB.java Wed Jul 03 15:04:53 2013 -0700 @@ -24,12 +24,22 @@ package sun.jvm.hotspot.tools.soql; +import sun.jvm.hotspot.debugger.JVMDebugger; import sun.jvm.hotspot.tools.*; import sun.jvm.hotspot.utilities.*; import sun.jvm.hotspot.utilities.soql.*; /** This is command line JavaScript debugger console */ public class JSDB extends Tool { + + public JSDB() { + super(); + } + + public JSDB(JVMDebugger d) { + super(d); + } + public static void main(String[] args) { JSDB jsdb = new JSDB(); jsdb.start(args); diff -r 536976a22f5f -r 70bea4a43c6d agent/src/share/classes/sun/jvm/hotspot/tools/soql/SOQL.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/soql/SOQL.java Wed Jul 03 14:50:10 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/soql/SOQL.java Wed Jul 03 15:04:53 2013 -0700 @@ -44,6 +44,14 @@ soql.stop(); } + public SOQL() { + super(); + } + + public SOQL(JVMDebugger d) { + super(d); + } + protected SOQLEngine soqlEngine; protected BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); protected PrintStream out = System.out; diff -r 536976a22f5f -r 70bea4a43c6d src/cpu/sparc/vm/frame_sparc.cpp --- a/src/cpu/sparc/vm/frame_sparc.cpp Wed Jul 03 14:50:10 2013 -0700 +++ b/src/cpu/sparc/vm/frame_sparc.cpp Wed Jul 03 15:04:53 2013 -0700 @@ -257,11 +257,6 @@ return false; } - // Could be a zombie method - if (sender_blob->is_zombie() || sender_blob->is_unloaded()) { - return false; - } - // It should be safe to construct the sender though it might not be valid frame sender(_SENDER_SP, younger_sp, adjusted_stack); diff -r 536976a22f5f -r 70bea4a43c6d src/os/solaris/dtrace/jhelper.d --- a/src/os/solaris/dtrace/jhelper.d Wed Jul 03 14:50:10 2013 -0700 +++ b/src/os/solaris/dtrace/jhelper.d Wed Jul 03 15:04:53 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -332,12 +332,15 @@ this->nameSymbol = copyin_ptr(this->constantPool + this->nameIndex * sizeof (pointer) + SIZE_ConstantPool); + /* The symbol is a CPSlot and has lower bit set to indicate metadata */ + this->nameSymbol &= (~1); /* remove metadata lsb */ this->nameSymbolLength = copyin_uint16(this->nameSymbol + OFFSET_Symbol_length); this->signatureSymbol = copyin_ptr(this->constantPool + this->signatureIndex * sizeof (pointer) + SIZE_ConstantPool); + this->signatureSymbol &= (~1); /* remove metadata lsb */ this->signatureSymbolLength = copyin_uint16(this->signatureSymbol + OFFSET_Symbol_length); diff -r 536976a22f5f -r 70bea4a43c6d src/share/vm/memory/filemap.cpp --- a/src/share/vm/memory/filemap.cpp Wed Jul 03 14:50:10 2013 -0700 +++ b/src/share/vm/memory/filemap.cpp Wed Jul 03 15:04:53 2013 -0700 @@ -549,3 +549,13 @@ return false; } + +void FileMapInfo::print_shared_spaces() { + gclog_or_tty->print_cr("Shared Spaces:"); + for (int i = 0; i < MetaspaceShared::n_regions; i++) { + struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[i]; + gclog_or_tty->print(" %s " INTPTR_FORMAT "-" INTPTR_FORMAT, + shared_region_name[i], + si->_base, si->_base + si->_used); + } +} diff -r 536976a22f5f -r 70bea4a43c6d src/share/vm/memory/filemap.hpp --- a/src/share/vm/memory/filemap.hpp Wed Jul 03 14:50:10 2013 -0700 +++ b/src/share/vm/memory/filemap.hpp Wed Jul 03 15:04:53 2013 -0700 @@ -149,6 +149,7 @@ // Return true if given address is in the mapped shared space. bool is_in_shared_space(const void* p) NOT_CDS_RETURN_(false); + void print_shared_spaces() NOT_CDS_RETURN; }; #endif // SHARE_VM_MEMORY_FILEMAP_HPP diff -r 536976a22f5f -r 70bea4a43c6d src/share/vm/memory/metaspace.cpp --- a/src/share/vm/memory/metaspace.cpp Wed Jul 03 14:50:10 2013 -0700 +++ b/src/share/vm/memory/metaspace.cpp Wed Jul 03 15:04:53 2013 -0700 @@ -70,7 +70,7 @@ SpecializedChunk = 128, ClassSmallChunk = 256, SmallChunk = 512, - ClassMediumChunk = 1 * K, + ClassMediumChunk = 4 * K, MediumChunk = 8 * K, HumongousChunkGranularity = 8 }; @@ -580,7 +580,6 @@ // Number of small chunks to allocate to a manager // If class space manager, small chunks are unlimited static uint const _small_chunk_limit; - bool has_small_chunk_limit() { return !vs_list()->is_class(); } // Sum of all space in allocated chunks size_t _allocated_blocks_words; @@ -1298,13 +1297,18 @@ bool MetaspaceGC::should_expand(VirtualSpaceList* vsl, size_t word_size) { - size_t committed_capacity_bytes = MetaspaceAux::allocated_capacity_bytes(); // If the user wants a limit, impose one. - size_t max_metaspace_size_bytes = MaxMetaspaceSize; - size_t metaspace_size_bytes = MetaspaceSize; - if (!FLAG_IS_DEFAULT(MaxMetaspaceSize) && - MetaspaceAux::reserved_in_bytes() >= MaxMetaspaceSize) { - return false; + // The reason for someone using this flag is to limit reserved space. So + // for non-class virtual space, compare against virtual spaces that are reserved. + // For class virtual space, we only compare against the committed space, not + // reserved space, because this is a larger space prereserved for compressed + // class pointers. + if (!FLAG_IS_DEFAULT(MaxMetaspaceSize)) { + size_t real_allocated = Metaspace::space_list()->virtual_space_total() + + MetaspaceAux::allocated_capacity_bytes(Metaspace::ClassType); + if (real_allocated >= MaxMetaspaceSize) { + return false; + } } // Class virtual space should always be expanded. Call GC for the other @@ -1318,11 +1322,12 @@ } - // If the capacity is below the minimum capacity, allow the // expansion. Also set the high-water-mark (capacity_until_GC) // to that minimum capacity so that a GC will not be induced // until that minimum capacity is exceeded. + size_t committed_capacity_bytes = MetaspaceAux::allocated_capacity_bytes(); + size_t metaspace_size_bytes = MetaspaceSize; if (committed_capacity_bytes < metaspace_size_bytes || capacity_until_GC() == 0) { set_capacity_until_GC(metaspace_size_bytes); @@ -1854,13 +1859,11 @@ Metachunk* chunk = chunks_in_use(index); // Count the free space in all the chunk but not the // current chunk from which allocations are still being done. - if (chunk != NULL) { - Metachunk* prev = chunk; - while (chunk != NULL && chunk != current_chunk()) { + while (chunk != NULL) { + if (chunk != current_chunk()) { result += chunk->free_word_size(); - prev = chunk; - chunk = chunk->next(); } + chunk = chunk->next(); } return result; } @@ -1949,8 +1952,7 @@ // chunks will be allocated. size_t chunk_word_size; if (chunks_in_use(MediumIndex) == NULL && - (!has_small_chunk_limit() || - sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit)) { + sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit) { chunk_word_size = (size_t) small_chunk_size(); if (word_size + Metachunk::overhead() > small_chunk_size()) { chunk_word_size = medium_chunk_size(); @@ -2659,10 +2661,10 @@ // Print total fragmentation for class and data metaspaces separately void MetaspaceAux::print_waste(outputStream* out) { - size_t specialized_waste = 0, small_waste = 0, medium_waste = 0, large_waste = 0; - size_t specialized_count = 0, small_count = 0, medium_count = 0, large_count = 0; - size_t cls_specialized_waste = 0, cls_small_waste = 0, cls_medium_waste = 0, cls_large_waste = 0; - size_t cls_specialized_count = 0, cls_small_count = 0, cls_medium_count = 0, cls_large_count = 0; + size_t specialized_waste = 0, small_waste = 0, medium_waste = 0; + size_t specialized_count = 0, small_count = 0, medium_count = 0, humongous_count = 0; + size_t cls_specialized_waste = 0, cls_small_waste = 0, cls_medium_waste = 0; + size_t cls_specialized_count = 0, cls_small_count = 0, cls_medium_count = 0, cls_humongous_count = 0; ClassLoaderDataGraphMetaspaceIterator iter; while (iter.repeat()) { @@ -2674,8 +2676,7 @@ small_count += msp->vsm()->sum_count_in_chunks_in_use(SmallIndex); medium_waste += msp->vsm()->sum_waste_in_chunks_in_use(MediumIndex); medium_count += msp->vsm()->sum_count_in_chunks_in_use(MediumIndex); - large_waste += msp->vsm()->sum_waste_in_chunks_in_use(HumongousIndex); - large_count += msp->vsm()->sum_count_in_chunks_in_use(HumongousIndex); + humongous_count += msp->vsm()->sum_count_in_chunks_in_use(HumongousIndex); cls_specialized_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(SpecializedIndex); cls_specialized_count += msp->class_vsm()->sum_count_in_chunks_in_use(SpecializedIndex); @@ -2683,20 +2684,23 @@ cls_small_count += msp->class_vsm()->sum_count_in_chunks_in_use(SmallIndex); cls_medium_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(MediumIndex); cls_medium_count += msp->class_vsm()->sum_count_in_chunks_in_use(MediumIndex); - cls_large_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(HumongousIndex); - cls_large_count += msp->class_vsm()->sum_count_in_chunks_in_use(HumongousIndex); + cls_humongous_count += msp->class_vsm()->sum_count_in_chunks_in_use(HumongousIndex); } } out->print_cr("Total fragmentation waste (words) doesn't count free space"); out->print_cr(" data: " SIZE_FORMAT " specialized(s) " SIZE_FORMAT ", " SIZE_FORMAT " small(s) " SIZE_FORMAT ", " - SIZE_FORMAT " medium(s) " SIZE_FORMAT, + SIZE_FORMAT " medium(s) " SIZE_FORMAT ", " + "large count " SIZE_FORMAT, specialized_count, specialized_waste, small_count, - small_waste, medium_count, medium_waste); + small_waste, medium_count, medium_waste, humongous_count); out->print_cr(" class: " SIZE_FORMAT " specialized(s) " SIZE_FORMAT ", " - SIZE_FORMAT " small(s) " SIZE_FORMAT, + SIZE_FORMAT " small(s) " SIZE_FORMAT ", " + SIZE_FORMAT " medium(s) " SIZE_FORMAT ", " + "large count " SIZE_FORMAT, cls_specialized_count, cls_specialized_waste, - cls_small_count, cls_small_waste); + cls_small_count, cls_small_waste, + cls_medium_count, cls_medium_waste, cls_humongous_count); } // Dump global metaspace things from the end of ClassLoaderDataGraph @@ -3037,18 +3041,24 @@ if (Verbose && TraceMetadataChunkAllocation) { gclog_or_tty->print_cr("Metaspace allocation failed for size " SIZE_FORMAT, word_size); - if (loader_data->metaspace_or_null() != NULL) loader_data->metaspace_or_null()->dump(gclog_or_tty); + if (loader_data->metaspace_or_null() != NULL) loader_data->dump(gclog_or_tty); MetaspaceAux::dump(gclog_or_tty); } // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support - report_java_out_of_memory("Metadata space"); + const char* space_string = (mdtype == ClassType) ? "Class Metadata space" : + "Metadata space"; + report_java_out_of_memory(space_string); if (JvmtiExport::should_post_resource_exhausted()) { JvmtiExport::post_resource_exhausted( JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR, - "Metadata space"); + space_string); } - THROW_OOP_0(Universe::out_of_memory_error_perm_gen()); + if (mdtype == ClassType) { + THROW_OOP_0(Universe::out_of_memory_error_class_metaspace()); + } else { + THROW_OOP_0(Universe::out_of_memory_error_metaspace()); + } } } return Metablock::initialize(result, word_size); diff -r 536976a22f5f -r 70bea4a43c6d src/share/vm/memory/metaspaceShared.cpp --- a/src/share/vm/memory/metaspaceShared.cpp Wed Jul 03 14:50:10 2013 -0700 +++ b/src/share/vm/memory/metaspaceShared.cpp Wed Jul 03 15:04:53 2013 -0700 @@ -826,35 +826,15 @@ bool reading() const { return true; } }; - -// Save bounds of shared spaces mapped in. -static char* _ro_base = NULL; -static char* _rw_base = NULL; -static char* _md_base = NULL; -static char* _mc_base = NULL; - // Return true if given address is in the mapped shared space. bool MetaspaceShared::is_in_shared_space(const void* p) { - if (_ro_base == NULL || _rw_base == NULL) { - return false; - } else { - return ((p >= _ro_base && p < (_ro_base + SharedReadOnlySize)) || - (p >= _rw_base && p < (_rw_base + SharedReadWriteSize))); - } + return UseSharedSpaces && FileMapInfo::current_info()->is_in_shared_space(p); } void MetaspaceShared::print_shared_spaces() { - gclog_or_tty->print_cr("Shared Spaces:"); - gclog_or_tty->print(" read-only " INTPTR_FORMAT "-" INTPTR_FORMAT, - _ro_base, _ro_base + SharedReadOnlySize); - gclog_or_tty->print(" read-write " INTPTR_FORMAT "-" INTPTR_FORMAT, - _rw_base, _rw_base + SharedReadWriteSize); - gclog_or_tty->cr(); - gclog_or_tty->print(" misc-data " INTPTR_FORMAT "-" INTPTR_FORMAT, - _md_base, _md_base + SharedMiscDataSize); - gclog_or_tty->print(" misc-code " INTPTR_FORMAT "-" INTPTR_FORMAT, - _mc_base, _mc_base + SharedMiscCodeSize); - gclog_or_tty->cr(); + if (UseSharedSpaces) { + FileMapInfo::current_info()->print_shared_spaces(); + } } @@ -874,6 +854,11 @@ assert(!DumpSharedSpaces, "Should not be called with DumpSharedSpaces"); + char* _ro_base = NULL; + char* _rw_base = NULL; + char* _md_base = NULL; + char* _mc_base = NULL; + // Map each shared region if ((_ro_base = mapinfo->map_region(ro)) != NULL && (_rw_base = mapinfo->map_region(rw)) != NULL && diff -r 536976a22f5f -r 70bea4a43c6d src/share/vm/memory/referenceProcessorStats.hpp --- a/src/share/vm/memory/referenceProcessorStats.hpp Wed Jul 03 14:50:10 2013 -0700 +++ b/src/share/vm/memory/referenceProcessorStats.hpp Wed Jul 03 15:04:53 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 diff -r 536976a22f5f -r 70bea4a43c6d src/share/vm/memory/universe.cpp --- a/src/share/vm/memory/universe.cpp Wed Jul 03 14:50:10 2013 -0700 +++ b/src/share/vm/memory/universe.cpp Wed Jul 03 15:04:53 2013 -0700 @@ -111,7 +111,8 @@ LatestMethodOopCache* Universe::_pd_implies_cache = NULL; ActiveMethodOopsCache* Universe::_reflect_invoke_cache = NULL; oop Universe::_out_of_memory_error_java_heap = NULL; -oop Universe::_out_of_memory_error_perm_gen = NULL; +oop Universe::_out_of_memory_error_metaspace = NULL; +oop Universe::_out_of_memory_error_class_metaspace = NULL; oop Universe::_out_of_memory_error_array_size = NULL; oop Universe::_out_of_memory_error_gc_overhead_limit = NULL; objArrayOop Universe::_preallocated_out_of_memory_error_array = NULL; @@ -180,7 +181,8 @@ f->do_oop((oop*)&_the_null_string); f->do_oop((oop*)&_the_min_jint_string); f->do_oop((oop*)&_out_of_memory_error_java_heap); - f->do_oop((oop*)&_out_of_memory_error_perm_gen); + f->do_oop((oop*)&_out_of_memory_error_metaspace); + f->do_oop((oop*)&_out_of_memory_error_class_metaspace); f->do_oop((oop*)&_out_of_memory_error_array_size); f->do_oop((oop*)&_out_of_memory_error_gc_overhead_limit); f->do_oop((oop*)&_preallocated_out_of_memory_error_array); @@ -563,7 +565,8 @@ // a potential loop which could happen if an out of memory occurs when attempting // to allocate the backtrace. return ((throwable() != Universe::_out_of_memory_error_java_heap) && - (throwable() != Universe::_out_of_memory_error_perm_gen) && + (throwable() != Universe::_out_of_memory_error_metaspace) && + (throwable() != Universe::_out_of_memory_error_class_metaspace) && (throwable() != Universe::_out_of_memory_error_array_size) && (throwable() != Universe::_out_of_memory_error_gc_overhead_limit)); } @@ -1014,7 +1017,8 @@ k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_OutOfMemoryError(), true, CHECK_false); k_h = instanceKlassHandle(THREAD, k); Universe::_out_of_memory_error_java_heap = k_h->allocate_instance(CHECK_false); - Universe::_out_of_memory_error_perm_gen = k_h->allocate_instance(CHECK_false); + Universe::_out_of_memory_error_metaspace = k_h->allocate_instance(CHECK_false); + Universe::_out_of_memory_error_class_metaspace = k_h->allocate_instance(CHECK_false); Universe::_out_of_memory_error_array_size = k_h->allocate_instance(CHECK_false); Universe::_out_of_memory_error_gc_overhead_limit = k_h->allocate_instance(CHECK_false); @@ -1047,7 +1051,9 @@ java_lang_Throwable::set_message(Universe::_out_of_memory_error_java_heap, msg()); msg = java_lang_String::create_from_str("Metadata space", CHECK_false); - java_lang_Throwable::set_message(Universe::_out_of_memory_error_perm_gen, msg()); + java_lang_Throwable::set_message(Universe::_out_of_memory_error_metaspace, msg()); + msg = java_lang_String::create_from_str("Class Metadata space", CHECK_false); + java_lang_Throwable::set_message(Universe::_out_of_memory_error_class_metaspace, msg()); msg = java_lang_String::create_from_str("Requested array size exceeds VM limit", CHECK_false); java_lang_Throwable::set_message(Universe::_out_of_memory_error_array_size, msg()); diff -r 536976a22f5f -r 70bea4a43c6d src/share/vm/memory/universe.hpp --- a/src/share/vm/memory/universe.hpp Wed Jul 03 14:50:10 2013 -0700 +++ b/src/share/vm/memory/universe.hpp Wed Jul 03 15:04:53 2013 -0700 @@ -178,10 +178,12 @@ static LatestMethodOopCache* _loader_addClass_cache; // method for registering loaded classes in class loader vector static LatestMethodOopCache* _pd_implies_cache; // method for checking protection domain attributes static ActiveMethodOopsCache* _reflect_invoke_cache; // method for security checks - static oop _out_of_memory_error_java_heap; // preallocated error object (no backtrace) - static oop _out_of_memory_error_perm_gen; // preallocated error object (no backtrace) - static oop _out_of_memory_error_array_size;// preallocated error object (no backtrace) - static oop _out_of_memory_error_gc_overhead_limit; // preallocated error object (no backtrace) + // preallocated error objects (no backtrace) + static oop _out_of_memory_error_java_heap; + static oop _out_of_memory_error_metaspace; + static oop _out_of_memory_error_class_metaspace; + static oop _out_of_memory_error_array_size; + static oop _out_of_memory_error_gc_overhead_limit; static Array* _the_empty_int_array; // Canonicalized int array static Array* _the_empty_short_array; // Canonicalized short array @@ -352,7 +354,8 @@ // may or may not have a backtrace. If error has a backtrace then the stack trace is already // filled in. static oop out_of_memory_error_java_heap() { return gen_out_of_memory_error(_out_of_memory_error_java_heap); } - static oop out_of_memory_error_perm_gen() { return gen_out_of_memory_error(_out_of_memory_error_perm_gen); } + static oop out_of_memory_error_metaspace() { return gen_out_of_memory_error(_out_of_memory_error_metaspace); } + static oop out_of_memory_error_class_metaspace() { return gen_out_of_memory_error(_out_of_memory_error_class_metaspace); } static oop out_of_memory_error_array_size() { return gen_out_of_memory_error(_out_of_memory_error_array_size); } static oop out_of_memory_error_gc_overhead_limit() { return gen_out_of_memory_error(_out_of_memory_error_gc_overhead_limit); } diff -r 536976a22f5f -r 70bea4a43c6d src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp Wed Jul 03 14:50:10 2013 -0700 +++ b/src/share/vm/prims/jni.cpp Wed Jul 03 15:04:53 2013 -0700 @@ -879,7 +879,7 @@ env, capacity); #endif /* USDT2 */ //%note jni_11 - if (capacity < 0 && capacity > MAX_REASONABLE_LOCAL_CAPACITY) { + if (capacity < 0 || capacity > MAX_REASONABLE_LOCAL_CAPACITY) { #ifndef USDT2 DTRACE_PROBE1(hotspot_jni, PushLocalFrame__return, JNI_ERR); #else /* USDT2 */ diff -r 536976a22f5f -r 70bea4a43c6d src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Wed Jul 03 14:50:10 2013 -0700 +++ b/src/share/vm/runtime/vmStructs.cpp Wed Jul 03 15:04:53 2013 -0700 @@ -437,10 +437,6 @@ static_field(Universe, _main_thread_group, oop) \ static_field(Universe, _system_thread_group, oop) \ static_field(Universe, _the_empty_class_klass_array, objArrayOop) \ - static_field(Universe, _out_of_memory_error_java_heap, oop) \ - static_field(Universe, _out_of_memory_error_perm_gen, oop) \ - static_field(Universe, _out_of_memory_error_array_size, oop) \ - static_field(Universe, _out_of_memory_error_gc_overhead_limit, oop) \ static_field(Universe, _null_ptr_exception_instance, oop) \ static_field(Universe, _arithmetic_exception_instance, oop) \ static_field(Universe, _vm_exception, oop) \ diff -r 536976a22f5f -r 70bea4a43c6d src/share/vm/services/memReporter.cpp --- a/src/share/vm/services/memReporter.cpp Wed Jul 03 14:50:10 2013 -0700 +++ b/src/share/vm/services/memReporter.cpp Wed Jul 03 15:04:53 2013 -0700 @@ -188,8 +188,8 @@ (MallocCallsitePointer*)prev_malloc_itr.current(); while (cur_malloc_callsite != NULL || prev_malloc_callsite != NULL) { - if (prev_malloc_callsite == NULL || - cur_malloc_callsite->addr() < prev_malloc_callsite->addr()) { + if (prev_malloc_callsite == NULL) { + assert(cur_malloc_callsite != NULL, "sanity check"); // this is a new callsite _outputer.diff_malloc_callsite(cur_malloc_callsite->addr(), amount_in_current_scale(cur_malloc_callsite->amount()), @@ -197,22 +197,42 @@ diff_in_current_scale(cur_malloc_callsite->amount(), 0), diff(cur_malloc_callsite->count(), 0)); cur_malloc_callsite = (MallocCallsitePointer*)cur_malloc_itr.next(); - } else if (cur_malloc_callsite == NULL || - cur_malloc_callsite->addr() > prev_malloc_callsite->addr()) { + } else if (cur_malloc_callsite == NULL) { + assert(prev_malloc_callsite != NULL, "Sanity check"); // this callsite is already gone _outputer.diff_malloc_callsite(prev_malloc_callsite->addr(), - amount_in_current_scale(0), 0, + 0, 0, diff_in_current_scale(0, prev_malloc_callsite->amount()), diff(0, prev_malloc_callsite->count())); prev_malloc_callsite = (MallocCallsitePointer*)prev_malloc_itr.next(); - } else { // the same callsite - _outputer.diff_malloc_callsite(cur_malloc_callsite->addr(), - amount_in_current_scale(cur_malloc_callsite->amount()), - cur_malloc_callsite->count(), - diff_in_current_scale(cur_malloc_callsite->amount(), prev_malloc_callsite->amount()), - diff(cur_malloc_callsite->count(), prev_malloc_callsite->count())); - cur_malloc_callsite = (MallocCallsitePointer*)cur_malloc_itr.next(); - prev_malloc_callsite = (MallocCallsitePointer*)prev_malloc_itr.next(); + } else { + assert(cur_malloc_callsite != NULL, "Sanity check"); + assert(prev_malloc_callsite != NULL, "Sanity check"); + if (cur_malloc_callsite->addr() < prev_malloc_callsite->addr()) { + // this is a new callsite + _outputer.diff_malloc_callsite(cur_malloc_callsite->addr(), + amount_in_current_scale(cur_malloc_callsite->amount()), + cur_malloc_callsite->count(), + diff_in_current_scale(cur_malloc_callsite->amount(), 0), + diff(cur_malloc_callsite->count(), 0)); + cur_malloc_callsite = (MallocCallsitePointer*)cur_malloc_itr.next(); + } else if (cur_malloc_callsite->addr() > prev_malloc_callsite->addr()) { + // this callsite is already gone + _outputer.diff_malloc_callsite(prev_malloc_callsite->addr(), + 0, 0, + diff_in_current_scale(0, prev_malloc_callsite->amount()), + diff(0, prev_malloc_callsite->count())); + prev_malloc_callsite = (MallocCallsitePointer*)prev_malloc_itr.next(); + } else { + // the same callsite + _outputer.diff_malloc_callsite(cur_malloc_callsite->addr(), + amount_in_current_scale(cur_malloc_callsite->amount()), + cur_malloc_callsite->count(), + diff_in_current_scale(cur_malloc_callsite->amount(), prev_malloc_callsite->amount()), + diff(cur_malloc_callsite->count(), prev_malloc_callsite->count())); + cur_malloc_callsite = (MallocCallsitePointer*)cur_malloc_itr.next(); + prev_malloc_callsite = (MallocCallsitePointer*)prev_malloc_itr.next(); + } } } diff -r 536976a22f5f -r 70bea4a43c6d src/share/vm/trace/trace.xml --- a/src/share/vm/trace/trace.xml Wed Jul 03 14:50:10 2013 -0700 +++ b/src/share/vm/trace/trace.xml Wed Jul 03 15:04:53 2013 -0700 @@ -158,7 +158,7 @@ - + @@ -203,7 +203,7 @@ - + @@ -211,7 +211,7 @@ - + @@ -240,14 +240,14 @@ - + - + - + diff -r 536976a22f5f -r 70bea4a43c6d src/share/vm/utilities/vmError.cpp --- a/src/share/vm/utilities/vmError.cpp Wed Jul 03 14:50:10 2013 -0700 +++ b/src/share/vm/utilities/vmError.cpp Wed Jul 03 15:04:53 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -799,6 +799,14 @@ VMError* volatile VMError::first_error = NULL; volatile jlong VMError::first_error_tid = -1; +// An error could happen before tty is initialized or after it has been +// destroyed. Here we use a very simple unbuffered fdStream for printing. +// Only out.print_raw() and out.print_raw_cr() should be used, as other +// printing methods need to allocate large buffer on stack. To format a +// string, use jio_snprintf() with a static buffer or use staticBufferStream. +fdStream VMError::out(defaultStream::output_fd()); +fdStream VMError::log; // error log used by VMError::report_and_die() + /** Expand a pattern into a buffer starting at pos and open a file using constructed path */ static int expand_and_open(const char* pattern, char* buf, size_t buflen, size_t pos) { int fd = -1; @@ -853,13 +861,6 @@ // Don't allocate large buffer on stack static char buffer[O_BUFLEN]; - // An error could happen before tty is initialized or after it has been - // destroyed. Here we use a very simple unbuffered fdStream for printing. - // Only out.print_raw() and out.print_raw_cr() should be used, as other - // printing methods need to allocate large buffer on stack. To format a - // string, use jio_snprintf() with a static buffer or use staticBufferStream. - static fdStream out(defaultStream::output_fd()); - // How many errors occurred in error handler when reporting first_error. static int recursive_error_count; @@ -868,7 +869,6 @@ static bool out_done = false; // done printing to standard out static bool log_done = false; // done saving error log static bool transmit_report_done = false; // done error reporting - static fdStream log; // error log // disble NMT to avoid further exception MemTracker::shutdown(MemTracker::NMT_error_reporting); diff -r 536976a22f5f -r 70bea4a43c6d src/share/vm/utilities/vmError.hpp --- a/src/share/vm/utilities/vmError.hpp Wed Jul 03 14:50:10 2013 -0700 +++ b/src/share/vm/utilities/vmError.hpp Wed Jul 03 15:04:53 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -96,6 +96,9 @@ return (id != OOM_MALLOC_ERROR) && (id != OOM_MMAP_ERROR); } + static fdStream out; + static fdStream log; // error log used by VMError::report_and_die() + public: // Constructor for crashes