Mercurial > hg > openjdk > jigsaw > hotspot
changeset 4610:45c724e2b43a default tip
Merge
line wrap: on
line diff
--- a/.hgtags Fri Apr 26 00:29:12 2013 -0700 +++ b/.hgtags Tue May 07 17:14:42 2013 -0700 @@ -24,6 +24,7 @@ fcb923bad68e2b10380a030ea83a723f4dc3d4d6 jdk7-b47 bcb33806d186561c781992e5f4d8a90bb033f9f0 jdk7-b48 8b22ccb5aba2c6c11bddf6488a7bb7ef5b4bf2be jdk7-b49 +dcfe9cb00de5a5cc491e8bef72174ef7d43f5d3e j1-2009-demo dae503d9f04c1a11e182dbf7f770509c28dc0609 jdk7-b50 2581d90c6c9b2012da930eb4742add94a03069a0 jdk7-b51 1b1e8f1a4fe8cebc01c022484f78148e17b62a0d jdk7-b52 @@ -51,6 +52,7 @@ f4b900403d6e4b0af51447bd13bbe23fe3a1dac7 jdk7-b74 d8dd291a362acb656026a9c0a9da48501505a1e7 jdk7-b75 9174bb32e934965288121f75394874eeb1fcb649 jdk7-b76 +5a91162840617825b2883c03338961e19c6b4e6a jigsaw-b01 455105fc81d941482f8f8056afaa7aa0949c9300 jdk7-b77 e703499b4b51e3af756ae77c3d5e8b3058a14e4e jdk7-b78 a5a6adfca6ecefb5894a848debabfe442ff50e25 jdk7-b79 @@ -81,7 +83,10 @@ fafab5d5349c7c066d677538db67a1ee0fb33bd2 hs15-b05 3f370a32906eb5ba993fabd7b4279be7f31052b9 jdk7-b83 ffc8d176b84bcfb5ac21302b4feb3b0c0d69b97c jdk7-b84 +4ac54e858f41e18ed0a669ff0da71185af43150d jigsaw-b02 6c9796468b91dcbb39e09dfa1baf9779ac45eb66 jdk7-b85 +f59c81b1afe92d624a32743c1a6d04469e3be5f2 jigsaw-b03 +c4854f8d4afee1a32cc5ac393163c06a61eaaf0c jigsaw-b04 418bc80ce13995149eadc9eecbba21d7a9fa02ae hs17-b10 bf823ef06b4f211e66988d76a2e2669be5c0820e jdk7-b86 07226e9eab8f74b37346b32715f829a2ef2c3188 hs18-b01 @@ -93,6 +98,8 @@ e0a1a502e402dbe7bf2d9102b4084a7e79a99a9b jdk7-b91 25f53b53aaa3eb8b2d5391a1e8de9a76ae1dd8a2 hs18-b03 3221d1887d30341bedfdac1dbf365ea41beff20f jdk7-b92 +8a6c97c3e8d18564171f2e0881d226c3855d3dbf jigsaw-b05 +10399ce7186641ae2b2b2e28d7324a72bc5e23b9 jigsaw-b06 310cdbc355355a13aa53c002b6bde4a8c5ba67ff hs18-b04 9d865fc2f644fdd9a0108fd6407944ee610aadd9 jdk7-b93 d38f45079fe98792a7381dbb4b64f5b589ec8c58 jdk7-b94 @@ -174,6 +181,7 @@ 9ad1548c6b63d596c411afc35147ffd5254426d9 hs21-b12 c149193c768b8b7233da4c3a3fdc0756b975848e hs21-b13 c149193c768b8b7233da4c3a3fdc0756b975848e jdk7-b143 +fe189d4a44e9e8f0c7d78fcbd1c63701745752ca jdk7-b144 0cc8a70952c368e06de2adab1f2649a408f5e577 jdk8-b01 31e253c1da429124bb87570ab095d9bc89850d0a jdk8-b02 3a2fb61165dfc72e398179a2796d740c8da5b8c0 jdk8-b03
--- a/.jcheck/conf Fri Apr 26 00:29:12 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -project=jdk8
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java Tue May 07 17:14:42 2013 -0700 @@ -0,0 +1,799 @@ +/* + * Copyright (c) 2002, 2012, 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. + * + */ + +package sun.jvm.hotspot.bugspot; + +import java.io.PrintStream; +import java.net.*; +import java.rmi.*; +import sun.jvm.hotspot.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.bsd.*; +import sun.jvm.hotspot.debugger.proc.*; +import sun.jvm.hotspot.debugger.cdbg.*; +import sun.jvm.hotspot.debugger.windbg.*; +import sun.jvm.hotspot.debugger.linux.*; +import sun.jvm.hotspot.debugger.sparc.*; +import sun.jvm.hotspot.debugger.remote.*; +import sun.jvm.hotspot.livejvm.*; +import sun.jvm.hotspot.memory.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; + +/** <P> This class wraps the basic functionality for connecting to the + * target process or debug server. It makes it simple to start up the + * debugging system. </P> + * + * <P> This agent (as compared to the HotSpotAgent) can connect to + * and interact with arbitrary processes. If the target process + * happens to be a HotSpot JVM, the Java debugging features of the + * Serviceability Agent are enabled. Further, if the Serviceability + * Agent's JVMDI module is loaded into the target VM, interaction + * with the live Java program is possible, specifically the catching + * of exceptions and setting of breakpoints. </P> + * + * <P> The BugSpot debugger requires that the underlying Debugger + * support C/C++ debugging via the CDebugger interface. </P> + * + * <P> FIXME: especially with the addition of remote debugging, this + * has turned into a mess; needs rethinking. </P> */ + +public class BugSpotAgent { + + private JVMDebugger debugger; + private MachineDescription machDesc; + private TypeDataBase db; + + private String os; + private String cpu; + private String fileSep; + + // The system can work in several ways: + // - Attaching to local process + // - Attaching to local core file + // - Connecting to remote debug server + // - Starting debug server for process + // - Starting debug server for core file + + // These are options for the "client" side of things + private static final int PROCESS_MODE = 0; + private static final int CORE_FILE_MODE = 1; + private static final int REMOTE_MODE = 2; + private int startupMode; + + // This indicates whether we are really starting a server or not + private boolean isServer; + + // All possible required information for connecting + private int pid; + private String executableName; + private String coreFileName; + private String debugServerID; + + // All needed information for server side + private String serverID; + + // Indicates whether we are attached to a HotSpot JVM or not + private boolean javaMode; + + // Indicates whether we have process control over a live HotSpot JVM + // or not; non-null if so. + private ServiceabilityAgentJVMDIModule jvmdi; + // While handling C breakpoints interactivity with the Java program + // is forbidden. Too many invariants are broken while the target is + // stopped at a C breakpoint to risk making JVMDI calls. + private boolean javaInteractionDisabled; + + private String[] jvmLibNames; + private String[] saLibNames; + + // FIXME: make these configurable, i.e., via a dotfile; also + // consider searching within the JDK from which this Java executable + // comes to find them + private static final String defaultDbxPathPrefix = "/net/jano.eng/export/disk05/hotspot/sa"; + private static final String defaultDbxSvcAgentDSOPathPrefix = "/net/jano.eng/export/disk05/hotspot/sa"; + + private static final boolean DEBUG; + static { + DEBUG = System.getProperty("sun.jvm.hotspot.bugspot.BugSpotAgent.DEBUG") + != null; + } + + static void debugPrintln(String str) { + if (DEBUG) { + System.err.println(str); + } + } + + static void showUsage() { + System.out.println(" You can also pass these -D options to java to specify where to find dbx and the \n" + + " Serviceability Agent plugin for dbx:"); + System.out.println(" -DdbxPathName=<path-to-dbx-executable>\n" + + " Default is derived from dbxPathPrefix"); + System.out.println(" or"); + System.out.println(" -DdbxPathPrefix=<xxx>\n" + + " where xxx is the path name of a dir structure that contains:\n" + + " <os>/<arch>/bin/dbx\n" + + " The default is " + defaultDbxPathPrefix); + System.out.println(" and"); + System.out.println(" -DdbxSvcAgentDSOPathName=<path-to-dbx-serviceability-agent-module>\n" + + " Default is determined from dbxSvcAgentDSOPathPrefix"); + System.out.println(" or"); + System.out.println(" -DdbxSvcAgentDSOPathPrefix=<xxx>\n" + + " where xxx is the pathname of a dir structure that contains:\n" + + " <os>/<arch>/bin/lib/libsvc_agent_dbx.so\n" + + " The default is " + defaultDbxSvcAgentDSOPathPrefix); + } + + public BugSpotAgent() { + // for non-server add shutdown hook to clean-up debugger in case + // of forced exit. For remote server, shutdown hook is added by + // DebugServer. + Runtime.getRuntime().addShutdownHook(new java.lang.Thread( + new Runnable() { + public void run() { + synchronized (BugSpotAgent.this) { + if (!isServer) { + detach(); + } + } + } + })); + } + + //-------------------------------------------------------------------------------- + // Accessors (once the system is set up) + // + + public synchronized Debugger getDebugger() { + return debugger; + } + + public synchronized CDebugger getCDebugger() { + return getDebugger().getCDebugger(); + } + + public synchronized ProcessControl getProcessControl() { + return getCDebugger().getProcessControl(); + } + + public synchronized TypeDataBase getTypeDataBase() { + return db; + } + + /** Indicates whether the target process is suspended + completely. Equivalent to getProcessControl().isSuspended(). */ + public synchronized boolean isSuspended() throws DebuggerException { + return getProcessControl().isSuspended(); + } + + /** Suspends the target process completely. Equivalent to + getProcessControl().suspend(). */ + public synchronized void suspend() throws DebuggerException { + getProcessControl().suspend(); + } + + /** Resumes the target process completely. Equivalent to + getProcessControl().suspend(). */ + public synchronized void resume() throws DebuggerException { + getProcessControl().resume(); + } + + /** Indicates whether we are attached to a Java HotSpot virtual + machine */ + public synchronized boolean isJavaMode() { + return javaMode; + } + + /** Temporarily disables interaction with the target process via + JVMDI. This is done while the target process is stopped at a C + breakpoint. Can be called even if the JVMDI agent has not been + initialized. */ + public synchronized void disableJavaInteraction() { + javaInteractionDisabled = true; + } + + /** Re-enables interaction with the target process via JVMDI. This + is done while the target process is continued past a C + braekpoint. Can be called even if the JVMDI agent has not been + initialized. */ + public synchronized void enableJavaInteraction() { + javaInteractionDisabled = false; + } + + /** Indicates whether Java interaction has been disabled */ + public synchronized boolean isJavaInteractionDisabled() { + return javaInteractionDisabled; + } + + /** Indicates whether we can talk to the Serviceability Agent's + JVMDI module to be able to set breakpoints */ + public synchronized boolean canInteractWithJava() { + return (jvmdi != null) && !javaInteractionDisabled; + } + + /** Suspends all Java threads in the target process. Can only be + called if we are attached to a HotSpot JVM and can connect to + the SA's JVMDI module. Must not be called when the target + process has been suspended with suspend(). */ + public synchronized void suspendJava() throws DebuggerException { + if (!canInteractWithJava()) { + throw new DebuggerException("Could not connect to SA's JVMDI module"); + } + if (jvmdi.isSuspended()) { + throw new DebuggerException("Target process already suspended via JVMDI"); + } + jvmdi.suspend(); + } + + /** Resumes all Java threads in the target process. Can only be + called if we are attached to a HotSpot JVM and can connect to + the SA's JVMDI module. Must not be called when the target + process has been suspended with suspend(). */ + public synchronized void resumeJava() throws DebuggerException { + if (!canInteractWithJava()) { + throw new DebuggerException("Could not connect to SA's JVMDI module"); + } + if (!jvmdi.isSuspended()) { + throw new DebuggerException("Target process already resumed via JVMDI"); + } + jvmdi.resume(); + } + + /** Indicates whether the target process has been suspended at the + Java language level via the SA's JVMDI module */ + public synchronized boolean isJavaSuspended() throws DebuggerException { + return jvmdi.isSuspended(); + } + + /** Toggle a Java breakpoint at the given location. */ + public synchronized ServiceabilityAgentJVMDIModule.BreakpointToggleResult + toggleJavaBreakpoint(String srcFileName, + String pkgName, + int lineNo) { + if (!canInteractWithJava()) { + throw new DebuggerException("Could not connect to SA's JVMDI module; can not toggle Java breakpoints"); + } + return jvmdi.toggleBreakpoint(srcFileName, pkgName, lineNo); + } + + /** Access to JVMDI module's eventPending */ + public synchronized boolean javaEventPending() throws DebuggerException { + if (!canInteractWithJava()) { + throw new DebuggerException("Could not connect to SA's JVMDI module; can not poll for Java debug events"); + } + return jvmdi.eventPending(); + } + + /** Access to JVMDI module's eventPoll */ + public synchronized Event javaEventPoll() throws DebuggerException { + if (!canInteractWithJava()) { + throw new DebuggerException("Could not connect to SA's JVMDI module; can not poll for Java debug events"); + } + return jvmdi.eventPoll(); + } + + /** Access to JVMDI module's eventContinue */ + public synchronized void javaEventContinue() throws DebuggerException { + if (!canInteractWithJava()) { + throw new DebuggerException("Could not connect to SA's JVMDI module; can not continue past Java debug events"); + } + jvmdi.eventContinue(); + } + + + // FIXME: add other accessors. For example, suspension and + // resumption should be done through this interface, as well as + // interaction with the live Java process such as breakpoint setting. + // Probably should not expose the ServiceabilityAgentJVMDIModule + // from this interface. + + //-------------------------------------------------------------------------------- + // Client-side operations + // + + /** This attaches to a process running on the local machine. */ + public synchronized void attach(int processID) + throws DebuggerException { + if (debugger != null) { + throw new DebuggerException("Already attached"); + } + pid = processID; + startupMode = PROCESS_MODE; + isServer = false; + go(); + } + + /** This opens a core file on the local machine */ + public synchronized void attach(String executableName, String coreFileName) + throws DebuggerException { + if (debugger != null) { + throw new DebuggerException("Already attached"); + } + if ((executableName == null) || (coreFileName == null)) { + throw new DebuggerException("Both the core file name and executable name must be specified"); + } + this.executableName = executableName; + this.coreFileName = coreFileName; + startupMode = CORE_FILE_MODE; + 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 + come in. */ + public synchronized void attach(String remoteServerID) + throws DebuggerException { + if (debugger != null) { + throw new DebuggerException("Already attached to a process"); + } + if (remoteServerID == null) { + throw new DebuggerException("Debug server id must be specified"); + } + + debugServerID = remoteServerID; + startupMode = REMOTE_MODE; + isServer = false; + go(); + } + + /** This should only be called by the user on the client machine, + not the server machine */ + public synchronized boolean detach() throws DebuggerException { + if (isServer) { + throw new DebuggerException("Should not call detach() for server configuration"); + } + return detachInternal(); + } + + //-------------------------------------------------------------------------------- + // Server-side operations + // + + /** This attaches to a process running on the local machine and + starts a debug server, allowing remote machines to connect and + examine this process. uniqueID is used to uniquely identify the + debuggee */ + public synchronized void startServer(int processID, String uniqueID) + throws DebuggerException { + if (debugger != null) { + throw new DebuggerException("Already attached"); + } + pid = processID; + startupMode = PROCESS_MODE; + isServer = true; + serverID = uniqueID; + go(); + } + + /** This attaches to a process running on the local machine and + starts a debug server, allowing remote machines to connect and + examine this process. */ + public synchronized void startServer(int processID) + throws DebuggerException { + startServer(processID, null); + } + + /** This opens a core file on the local machine and starts a debug + server, allowing remote machines to connect and examine this + core file. uniqueID is used to uniquely identify the + debuggee */ + public synchronized void startServer(String executableName, String coreFileName, + String uniqueID) + throws DebuggerException { + if (debugger != null) { + throw new DebuggerException("Already attached"); + } + if ((executableName == null) || (coreFileName == null)) { + throw new DebuggerException("Both the core file name and Java executable name must be specified"); + } + this.executableName = executableName; + this.coreFileName = coreFileName; + startupMode = CORE_FILE_MODE; + isServer = true; + serverID = uniqueID; + go(); + } + + /** This opens a core file on the local machine and starts a debug + server, allowing remote machines to connect and examine this + core file.*/ + public synchronized void startServer(String executableName, String coreFileName) + throws DebuggerException { + startServer(executableName, coreFileName, null); + } + + /** This may only be called on the server side after startServer() + has been called */ + public synchronized boolean shutdownServer() throws DebuggerException { + if (!isServer) { + throw new DebuggerException("Should not call shutdownServer() for client configuration"); + } + return detachInternal(); + } + + + //-------------------------------------------------------------------------------- + // Internals only below this point + // + + private boolean detachInternal() { + if (debugger == null) { + return false; + } + if (canInteractWithJava()) { + jvmdi.detach(); + jvmdi = null; + } + boolean retval = true; + if (!isServer) { + VM.shutdown(); + } + // We must not call detach() if we are a client and are connected + // to a remote debugger + Debugger dbg = null; + DebuggerException ex = null; + if (isServer) { + try { + RMIHelper.unbind(serverID); + } + catch (DebuggerException de) { + ex = de; + } + dbg = debugger; + } else { + if (startupMode != REMOTE_MODE) { + dbg = debugger; + } + } + if (dbg != null) { + retval = dbg.detach(); + } + + debugger = null; + machDesc = null; + db = null; + if (ex != null) { + throw(ex); + } + return retval; + } + + private void go() { + setupDebugger(); + javaMode = setupVM(); + } + + private void setupDebugger() { + if (startupMode != REMOTE_MODE) { + // + // Local mode (client attaching to local process or setting up + // 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"); + + if (os.equals("solaris")) { + setupDebuggerSolaris(); + } else if (os.equals("win32")) { + setupDebuggerWin32(); + } else if (os.equals("linux")) { + setupDebuggerLinux(); + } else if (os.equals("bsd")) { + setupDebuggerBsd(); + } else { + // Add support for more operating systems here + throw new DebuggerException("Operating system " + os + " not yet supported"); + } + if (isServer) { + RemoteDebuggerServer remote = null; + try { + remote = new RemoteDebuggerServer(debugger); + } + catch (RemoteException rem) { + throw new DebuggerException(rem); + } + RMIHelper.rebind(serverID, remote); + } + } else { + // + // Remote mode (client attaching to server) + // + + // Create and install a security manager + + // FIXME: currently commented out because we were having + // security problems since we're "in the sun.* hierarchy" here. + // Perhaps a permissive policy file would work around this. In + // the long run, will probably have to move into com.sun.*. + + // if (System.getSecurityManager() == null) { + // System.setSecurityManager(new RMISecurityManager()); + // } + + connectRemoteDebugger(); + } + } + + private boolean setupVM() { + // We need to instantiate a HotSpotTypeDataBase on both the client + // and server machine. On the server it is only currently used to + // configure the Java primitive type sizes (which we should + // consider making constant). On the client it is used to + // configure the VM. + + try { + if (os.equals("solaris")) { + db = new HotSpotTypeDataBase(machDesc, new HotSpotSolarisVtblAccess(debugger, jvmLibNames), + debugger, jvmLibNames); + } else if (os.equals("win32")) { + db = new HotSpotTypeDataBase(machDesc, new Win32VtblAccess(debugger, jvmLibNames), + debugger, jvmLibNames); + } else if (os.equals("linux")) { + db = new HotSpotTypeDataBase(machDesc, new LinuxVtblAccess(debugger, jvmLibNames), + debugger, jvmLibNames); + } else if (os.equals("bsd")) { + db = new HotSpotTypeDataBase(machDesc, new BsdVtblAccess(debugger, jvmLibNames), + debugger, jvmLibNames); + } else { + throw new DebuggerException("OS \"" + os + "\" not yet supported (no VtblAccess implemented yet)"); + } + } + catch (NoSuchSymbolException e) { + e.printStackTrace(); + return false; + } + + if (startupMode != REMOTE_MODE) { + // Configure the debugger with the primitive type sizes just obtained from the VM + debugger.configureJavaPrimitiveTypeSizes(db.getJBooleanType().getSize(), + db.getJByteType().getSize(), + db.getJCharType().getSize(), + db.getJDoubleType().getSize(), + db.getJFloatType().getSize(), + db.getJIntType().getSize(), + db.getJLongType().getSize(), + db.getJShortType().getSize()); + } + + if (!isServer) { + // Do not initialize the VM on the server (unnecessary, since it's + // instantiated on the client) + VM.initialize(db, debugger); + } + + try { + jvmdi = new ServiceabilityAgentJVMDIModule(debugger, saLibNames); + if (jvmdi.canAttach()) { + jvmdi.attach(); + jvmdi.setCommandTimeout(6000); + debugPrintln("Attached to Serviceability Agent's JVMDI module."); + // Jog VM to suspended point with JVMDI module + resume(); + suspendJava(); + suspend(); + debugPrintln("Suspended all Java threads."); + } else { + debugPrintln("Could not locate SA's JVMDI module; skipping attachment"); + jvmdi = null; + } + } catch (Exception e) { + e.printStackTrace(); + jvmdi = null; + } + + return true; + } + + //-------------------------------------------------------------------------------- + // OS-specific debugger setup/connect routines + // + + // + // Solaris + // + + private void setupDebuggerSolaris() { + setupJVMLibNamesSolaris(); + ProcDebuggerLocal dbg = new ProcDebuggerLocal(null, true); + debugger = dbg; + attachDebugger(); + + // Set up CPU-dependent stuff + if (cpu.equals("x86")) { + machDesc = new MachineDescriptionIntelX86(); + } else if (cpu.equals("sparc")) { + int addressSize = dbg.getRemoteProcessAddressSize(); + if (addressSize == -1) { + throw new DebuggerException("Error occurred while trying to determine the remote process's address size"); + } + + if (addressSize == 32) { + machDesc = new MachineDescriptionSPARC32Bit(); + } else if (addressSize == 64) { + machDesc = new MachineDescriptionSPARC64Bit(); + } else { + throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC"); + } + } else if (cpu.equals("amd64")) { + machDesc = new MachineDescriptionAMD64(); + } else { + throw new DebuggerException("Solaris only supported on sparc/sparcv9/x86/amd64"); + } + + dbg.setMachineDescription(machDesc); + } + + private void connectRemoteDebugger() throws DebuggerException { + RemoteDebugger remote = + (RemoteDebugger) RMIHelper.lookup(debugServerID); + debugger = new RemoteDebuggerClient(remote); + machDesc = ((RemoteDebuggerClient) debugger).getMachineDescription(); + os = debugger.getOS(); + if (os.equals("solaris")) { + setupJVMLibNamesSolaris(); + } else if (os.equals("win32")) { + setupJVMLibNamesWin32(); + } else if (os.equals("linux")) { + setupJVMLibNamesLinux(); + } else if (os.equals("bsd")) { + setupJVMLibNamesBsd(); + } else { + throw new RuntimeException("Unknown OS type"); + } + + cpu = debugger.getCPU(); + } + + private void setupJVMLibNamesSolaris() { + jvmLibNames = new String[] { "libjvm.so", "libjvm_g.so", "gamma_g" }; + saLibNames = new String[] { "libsa.so", "libsa_g.so" }; + } + + // + // Win32 + // + + private void setupDebuggerWin32() { + setupJVMLibNamesWin32(); + + if (cpu.equals("x86")) { + machDesc = new MachineDescriptionIntelX86(); + } else if (cpu.equals("amd64")) { + machDesc = new MachineDescriptionAMD64(); + } else if (cpu.equals("ia64")) { + machDesc = new MachineDescriptionIA64(); + } else { + throw new DebuggerException("Win32 supported under x86, amd64 and ia64 only"); + } + + // Note we do not use a cache for the local debugger in server + // mode; it will be taken care of on the client side (once remote + // debugging is implemented). + + debugger = new WindbgDebuggerLocal(machDesc, !isServer); + + attachDebugger(); + } + + private void setupJVMLibNamesWin32() { + jvmLibNames = new String[] { "jvm.dll", "jvm_g.dll" }; + saLibNames = new String[] { "sa.dll", "sa_g.dll" }; + } + + // + // Linux + // + + private void setupDebuggerLinux() { + setupJVMLibNamesLinux(); + + if (cpu.equals("x86")) { + machDesc = new MachineDescriptionIntelX86(); + } else if (cpu.equals("ia64")) { + machDesc = new MachineDescriptionIA64(); + } else if (cpu.equals("amd64")) { + machDesc = new MachineDescriptionAMD64(); + } else if (cpu.equals("sparc")) { + if (LinuxDebuggerLocal.getAddressSize()==8) { + machDesc = new MachineDescriptionSPARC64Bit(); + } else { + machDesc = new MachineDescriptionSPARC32Bit(); + } + } else { + try { + machDesc = (MachineDescription) + Class.forName("sun.jvm.hotspot.debugger.MachineDescription" + + cpu.toUpperCase()).newInstance(); + } catch (Exception e) { + throw new DebuggerException("unsupported machine type"); + } + } + + + // Note we do not use a cache for the local debugger in server + // mode; it will be taken care of on the client side (once remote + // debugging is implemented). + + debugger = new LinuxDebuggerLocal(machDesc, !isServer); + attachDebugger(); + } + + private void setupJVMLibNamesLinux() { + // same as solaris + setupJVMLibNamesSolaris(); + } + + // + // BSD + // + + private void setupDebuggerBsd() { + setupJVMLibNamesBsd(); + + if (cpu.equals("x86")) { + machDesc = new MachineDescriptionIntelX86(); + } else if (cpu.equals("amd64") || (cpu.equals("x86_64"))) { + machDesc = new MachineDescriptionAMD64(); + } else { + throw new DebuggerException("Bsd only supported on x86/x86_64. Current arch: " + cpu); + } + + // Note we do not use a cache for the local debugger in server + // mode; it will be taken care of on the client side (once remote + // debugging is implemented). + + debugger = new BsdDebuggerLocal(machDesc, !isServer); + attachDebugger(); + } + + private void setupJVMLibNamesBsd() { + // same as solaris + setupJVMLibNamesSolaris(); + } + + /** Convenience routine which should be called by per-platform + debugger setup. Should not be called when startupMode is + REMOTE_MODE. */ + private void attachDebugger() { + if (startupMode == PROCESS_MODE) { + debugger.attach(pid); + } else if (startupMode == CORE_FILE_MODE) { + debugger.attach(executableName, coreFileName); + } else { + throw new DebuggerException("Should not call attach() for startupMode == " + startupMode); + } + } +}
--- a/make/bsd/makefiles/sa.make Fri Apr 26 00:29:12 2013 -0700 +++ b/make/bsd/makefiles/sa.make Tue May 07 17:14:42 2013 -0700 @@ -50,6 +50,12 @@ # are in the regular classes.jar file. APPLE_JAR=$(BOOT_JAVA_HOME)/bundle/Classes/classes.jar SA_CLASSPATH=$(shell test -f $(APPLE_JAR) && echo $(APPLE_JAR)) + # if above file doesn't exist, use the openjdk version + ifeq ($(SA_CLASSPATH),) + # MMM Doesn't matter if in modules case the file doesn't exist + # some path needs to be set. + SA_CLASSPATH=$(BOOT_JAVA_HOME)/lib/sa-jdi.jar + endif endif endif else
--- a/make/linux/makefiles/mapfile-vers-debug Fri Apr 26 00:29:12 2013 -0700 +++ b/make/linux/makefiles/mapfile-vers-debug Tue May 07 17:14:42 2013 -0700 @@ -83,6 +83,7 @@ JVM_DumpThreads; JVM_EnableCompiler; JVM_Exit; + JVM_ExtendBootClassPath; JVM_FillInStackTrace; JVM_FindClassFromClass; JVM_FindClassFromClassLoader; @@ -153,6 +154,7 @@ JVM_GetMethodIxSignatureUTF; JVM_GetMethodParameterAnnotations; JVM_GetMethodParameters; + JVM_GetModuleLoader; JVM_GetMethodTypeAnnotations; JVM_GetPrimitiveArrayElement; JVM_GetProtectionDomain;
--- a/make/linux/makefiles/mapfile-vers-product Fri Apr 26 00:29:12 2013 -0700 +++ b/make/linux/makefiles/mapfile-vers-product Tue May 07 17:14:42 2013 -0700 @@ -83,6 +83,7 @@ JVM_DumpThreads; JVM_EnableCompiler; JVM_Exit; + JVM_ExtendBootClassPath; JVM_FillInStackTrace; JVM_FindClassFromClass; JVM_FindClassFromClassLoader; @@ -153,6 +154,7 @@ JVM_GetMethodIxSignatureUTF; JVM_GetMethodParameterAnnotations; JVM_GetMethodParameters; + JVM_GetModuleLoader; JVM_GetMethodTypeAnnotations; JVM_GetPrimitiveArrayElement; JVM_GetProtectionDomain;
--- a/make/solaris/makefiles/mapfile-vers Fri Apr 26 00:29:12 2013 -0700 +++ b/make/solaris/makefiles/mapfile-vers Tue May 07 17:14:42 2013 -0700 @@ -83,6 +83,7 @@ JVM_DumpThreads; JVM_EnableCompiler; JVM_Exit; + JVM_ExtendBootClassPath; JVM_FillInStackTrace; JVM_FindClassFromClass; JVM_FindClassFromClassLoader;
--- a/make/windows/makefiles/vm.make Fri Apr 26 00:29:12 2013 -0700 +++ b/make/windows/makefiles/vm.make Tue May 07 17:14:42 2013 -0700 @@ -104,7 +104,8 @@ /export:JVM_GetVersionInfo \ /export:JVM_GetThreadStateNames \ /export:JVM_GetThreadStateValues \ - /export:JVM_InitAgentProperties + /export:JVM_InitAgentProperties \ + /export:JVM_ExtendBootClassPath CXX_INCLUDE_DIRS=/I "..\generated"
--- a/src/share/vm/classfile/classLoader.cpp Fri Apr 26 00:29:12 2013 -0700 +++ b/src/share/vm/classfile/classLoader.cpp Tue May 07 17:14:42 2013 -0700 @@ -28,6 +28,7 @@ #include "classfile/classLoader.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/javaClasses.hpp" +#include "classfile/jigsaw.h" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "compiler/compileBroker.hpp" @@ -90,6 +91,13 @@ static GetNextEntry_t GetNextEntry = NULL; static canonicalize_fn_t CanonicalizeEntry = NULL; +// Entry points for libjava.so for loading modules +static load_module_context_fn_t JDK_LoadContexts = NULL; +static find_local_module_class_fn_t JDK_FindLocalClass = NULL; +static read_local_module_class_fn_t JDK_ReadLocalClass = NULL; +static get_module_info_fn_t JDK_GetModuleInfo = NULL; +static get_system_module_library_fn_t JDK_GetSystemModuleLibraryPath = NULL; + // Globals PerfCounter* ClassLoader::_perf_accumulated_time = NULL; @@ -107,12 +115,17 @@ PerfCounter* ClassLoader::_perf_sys_class_lookup_time = NULL; PerfCounter* ClassLoader::_perf_shared_classload_time = NULL; PerfCounter* ClassLoader::_perf_sys_classload_time = NULL; +PerfCounter* ClassLoader::_perf_sys_classload_selftime = NULL; +PerfCounter* ClassLoader::_perf_sys_classload_count = NULL; PerfCounter* ClassLoader::_perf_app_classload_time = NULL; PerfCounter* ClassLoader::_perf_app_classload_selftime = NULL; PerfCounter* ClassLoader::_perf_app_classload_count = NULL; PerfCounter* ClassLoader::_perf_define_appclasses = NULL; PerfCounter* ClassLoader::_perf_define_appclass_time = NULL; PerfCounter* ClassLoader::_perf_define_appclass_selftime = NULL; +PerfCounter* ClassLoader::_perf_define_sysclasses = NULL; +PerfCounter* ClassLoader::_perf_define_sysclass_time = NULL; +PerfCounter* ClassLoader::_perf_define_sysclass_selftime = NULL; PerfCounter* ClassLoader::_perf_app_classfile_bytes_read = NULL; PerfCounter* ClassLoader::_perf_sys_classfile_bytes_read = NULL; PerfCounter* ClassLoader::_sync_systemLoaderLockContentionRate = NULL; @@ -123,10 +136,16 @@ PerfCounter* ClassLoader::_unsafe_defineClassCallCounter = NULL; PerfCounter* ClassLoader::_isUnsyncloadClass = NULL; PerfCounter* ClassLoader::_load_instance_class_failCounter = NULL; +PerfCounter* ClassLoader::_perf_getstackacc_count = NULL; +PerfCounter* ClassLoader::_perf_getstackacc_frames_count = NULL; +PerfCounter* ClassLoader::_perf_getstackacc_priv_count = NULL; +PerfCounter* ClassLoader::_perf_getstackacc_newacc_count = NULL; ClassPathEntry* ClassLoader::_first_entry = NULL; ClassPathEntry* ClassLoader::_last_entry = NULL; PackageHashtable* ClassLoader::_package_hash_table = NULL; +void* ClassLoader::_base_context = NULL; +char* ClassLoader::_libpath = NULL; // helper routines bool string_starts_with(const char* str, const char* str_to_find) { @@ -343,7 +362,10 @@ const char* known_version = "% VERSION 2"; char* meta_index_path = Arguments::get_meta_index_path(); char* meta_index_dir = Arguments::get_meta_index_dir(); - FILE* file = fopen(meta_index_path, "r"); + FILE* file = NULL; + if (meta_index_path != NULL) { // Will be null if we booted from a module + file = fopen(meta_index_path, "r"); + } int line_no = 0; if (file != NULL) { ResourceMark rm; @@ -448,6 +470,7 @@ int len = (int)strlen(sys_class_path); int end = 0; + int total_found = 0; // Iterate over class path entries for (int start = 0; start < len; start = end) { @@ -457,7 +480,20 @@ char* path = NEW_C_HEAP_ARRAY(char, end-start+1, mtClass); strncpy(path, &sys_class_path[start], end-start); path[end-start] = '\0'; - update_class_path_entry_list(path, false); + bool found = update_class_path_entry_list(path, false); + + if (found) { + total_found++; + } + + if (UseModuleNativeLibs && Arguments::has_module_image()) { + if (Arguments::boot_module_index() == 0) { + if (strcmp(path, Arguments::get_boot_module_base()) == 0) { + Arguments::set_boot_module_index(total_found-1); + } + } + } + FREE_C_HEAP_ARRAY(char, path, mtClass); while (sys_class_path[end] == os::path_separator()[0]) { end++; @@ -572,21 +608,28 @@ } } -void ClassLoader::update_class_path_entry_list(const char *path, +// returns true if entry is added to the list +bool ClassLoader::update_class_path_entry_list(const char *path, bool check_for_duplicates) { struct stat st; + bool found = false; if (os::stat((char *)path, &st) == 0) { // File or directory found ClassPathEntry* new_entry = NULL; create_class_path_entry((char *)path, st, &new_entry, LazyBootClassLoader); - // The kernel VM adds dynamically to the end of the classloader path and - // doesn't reorder the bootclasspath which would break java.lang.Package - // (see PackageInfo). - // Add new entry to linked list + // The kernel VM, and Jigsaw, add dynamically to the end of the classloader + // path and don't reorder the bootclasspath, which would break + // java.lang.Package (see PackageInfo). if (!check_for_duplicates || !contains_entry(new_entry)) { + // Add new entry to linked list add_to_list(new_entry); + found = true; + if (TraceClassLoading) { + print_bootclasspath(); + } } } + return found; } void ClassLoader::print_bootclasspath() { @@ -632,6 +675,23 @@ // This lookup only works on 1.3. Do not check for non-null here } +void ClassLoader::load_module_search_library() { + // Lookup module entries in libjava.dll + void *javalib_handle = os::native_java_library(); + + JDK_GetSystemModuleLibraryPath = CAST_TO_FN_PTR(get_system_module_library_fn_t, os::dll_lookup(javalib_handle, "JDK_GetSystemModuleLibraryPath")); + + JDK_LoadContexts = CAST_TO_FN_PTR(load_module_context_fn_t, os::dll_lookup(javalib_handle, "JDK_LoadContexts")); + JDK_FindLocalClass = CAST_TO_FN_PTR(find_local_module_class_fn_t, os::dll_lookup(javalib_handle, "JDK_FindLocalClass")); + JDK_ReadLocalClass = CAST_TO_FN_PTR(read_local_module_class_fn_t, os::dll_lookup(javalib_handle, "JDK_ReadLocalClass")); + JDK_GetModuleInfo = CAST_TO_FN_PTR(get_module_info_fn_t, os::dll_lookup(javalib_handle, "JDK_GetModuleInfo")); + + if (JDK_LoadContexts == NULL || JDK_FindLocalClass == NULL || JDK_ReadLocalClass == NULL || JDK_GetSystemModuleLibraryPath == NULL) { + vm_exit_during_initialization("Corrupted Module Native library"); + } +} + + // PackageInfo data exists in order to support the java.lang.Package // class. A Package object provides information about a java package // (version, vendor, etc.) which originates in the manifest of the jar @@ -834,7 +894,7 @@ } } - +// With module images, the JDK has a module loader that knows package -> module source information oop ClassLoader::get_system_package(const char* name, TRAPS) { PackageInfo* pp; { @@ -849,7 +909,7 @@ } } - +// With module images, the JDK has a module loader that knows package -> module source information objArrayOop ClassLoader::get_system_packages(TRAPS) { ResourceMark rm(THREAD); int nof_entries; @@ -875,8 +935,7 @@ return result(); } - -instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) { +instanceKlassHandle ClassLoader::load_class_from_module_library(Symbol* h_name, TRAPS) { ResourceMark rm(THREAD); EventMark m("loading class " INTPTR_FORMAT, (address)h_name); ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion); @@ -885,18 +944,167 @@ // st.print() uses too much stack space while handling a StackOverflowError // st.print("%s.class", h_name->as_utf8()); st.print_raw(h_name->as_utf8()); + // st.print_raw(".class"); + char* name = st.as_string(); + + instanceKlassHandle result; + ClassFileStream* stream = NULL; + + char *java_home = Arguments::get_java_home(); + // TODO: check modulequery format? + // TODO: note: libs don't support @version yet - just give a classname + const char* modulequery = Arguments::sun_java_launcher_module(); + const char* modulepath = NULL; + + void *module; + + jint len = 0; + jint getliberr = 0; + jint contexterr = 0; + jint finderr = 0; + jint readerr = 0; + jint getinfoerr = 0; + + JavaThread* jt = (JavaThread*)THREAD; + + { + ThreadToNativeFromVM ttn(jt); + if (_base_context == NULL) { + _libpath = (char *)Arguments::sun_java_launcher_module_library(); + if (_libpath != NULL) { + // check if file exists + struct stat st; + if (os::stat(_libpath, &st) != 0) { + _libpath = NULL; + } + } + + if (_libpath == NULL) { + // First find the default module library if not set via -L + _libpath = (char*) NEW_RESOURCE_ARRAY(char, JVM_MAXPATHLEN); + getliberr = JDK_GetSystemModuleLibraryPath(java_home, _libpath, JVM_MAXPATHLEN); + } + if (getliberr == 0) { + // Next load the context of the module query (name@version) in the module library + contexterr = JDK_LoadContexts(_libpath, modulepath, modulequery, &_base_context); + if (contexterr != 0) { + if (TraceClassLoading && Verbose) { + tty->print("[module context not found for modulequery(null for non-modular app): %s in libpath:%s, error:%d]\n", + modulequery==NULL ? "NULL" : modulequery, _libpath, contexterr); + } + } + } else { + if (TraceClassLoading && Verbose) { + tty->print("[default module library not found, error:%d]\n", getliberr); + } + } + } + + if (_base_context != NULL) { + PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(), + jt->get_thread_stat()->perf_timers_addr(), + PerfClassTraceTime::CLASS_LOAD); + // Find the class local to the base context + finderr = JDK_FindLocalClass(_base_context, name, &module, &len); + + if (finderr == 0) { + // Read contents into resource array + u1* buffer = NEW_RESOURCE_ARRAY(u1, len); + jint readerr = JDK_ReadLocalClass(module, name, buffer, len); + if (readerr == 0) { + jmodule minfo; + JDK_GetModuleInfo(module, &minfo); + if (UsePerfData) { + ClassLoader::perf_sys_classfile_bytes_read()->inc(len); + } + stream = new ClassFileStream(buffer, len, (char*)minfo.source); // Resource allocated + } + } else { + if (TraceClassLoading && Verbose) { + tty->print("[module class not found:%s, err:%d]\n", name, finderr); + } + } + // close lookup_time + } + } + + if (stream != NULL) { + instanceKlassHandle ikh; + { + PerfClassTraceTime vmtimer(ClassLoader::perf_define_sysclass_time(), + ClassLoader::perf_define_sysclass_selftime(), + ClassLoader::perf_define_sysclasses(), + jt->get_thread_stat()->perf_recursion_counts_addr(), + jt->get_thread_stat()->perf_timers_addr(), + PerfClassTraceTime::DEFINE_CLASS); + + // class file found, parse it + ClassFileParser parser(stream); + ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); + Handle protection_domain; + TempNewSymbol parsed_name = NULL; + ikh = parser.parseClassFile(h_name, + loader_data, + protection_domain, + parsed_name, + false, + CHECK_(result)); + } // end of timer + // add to package table + // JDK will match this name and look up the actual module in the module library + if (add_package(name, Arguments::boot_module_index(), THREAD)) { + result = ikh; + } + } + return result; +} + +instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) { + + instanceKlassHandle nk; + + // Have to check both, command-line can set UseModuleNativeLibs after + // we determine there is no module image + if (UseModuleNativeLibs && Arguments::has_module_image()) { + // search prepended path + nk = load_class_from_classpath(h_name, 0, Arguments::boot_module_index(),CHECK_(nk)); + // search module library + if (nk == NULL) { + nk = load_class_from_module_library(h_name, CHECK_(nk)); + // search appended path + if (nk == NULL) { + nk = load_class_from_classpath(h_name, Arguments::boot_module_index()+1, JVM_MAXPATHLEN, CHECK_(nk)); + } + } + } else { + nk = load_class_from_classpath(h_name, 0, JVM_MAXPATHLEN, CHECK_(nk)); + } + return nk; +} + +// Search bootclasspath from (inclusive) to end (exclusive) +instanceKlassHandle ClassLoader::load_class_from_classpath(Symbol* h_name, int start, int end, TRAPS) { + ResourceMark rm(THREAD); + EventMark m("loading class " INTPTR_FORMAT, (address)h_name); + ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion); + JavaThread* jt = (JavaThread*)THREAD; + + stringStream st; + // st.print() uses too much stack space while handling a StackOverflowError + // st.print("%s.class", h_name->as_utf8()); + st.print_raw(h_name->as_utf8()); st.print_raw(".class"); char* name = st.as_string(); // Lookup stream for parsing .class file ClassFileStream* stream = NULL; - int classpath_index = 0; + int classpath_index = start; { PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(), - ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(), + jt->get_thread_stat()->perf_timers_addr(), PerfClassTraceTime::CLASS_LOAD); ClassPathEntry* e = _first_entry; - while (e != NULL) { + while (e != NULL && classpath_index < end) { stream = e->open_stream(name); if (stream != NULL) { break; @@ -908,19 +1116,28 @@ instanceKlassHandle h; if (stream != NULL) { + instanceKlassHandle result; + { + PerfClassTraceTime vmtimer(ClassLoader::perf_define_sysclass_time(), + ClassLoader::perf_define_sysclass_selftime(), + ClassLoader::perf_define_sysclasses(), + jt->get_thread_stat()->perf_recursion_counts_addr(), + jt->get_thread_stat()->perf_timers_addr(), + PerfClassTraceTime::DEFINE_CLASS); - // class file found, parse it - ClassFileParser parser(stream); - ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); - Handle protection_domain; - TempNewSymbol parsed_name = NULL; - instanceKlassHandle result = parser.parseClassFile(h_name, - loader_data, - protection_domain, - parsed_name, - false, - CHECK_(h)); + // class file found, parse it + ClassFileParser parser(stream); + ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); + Handle protection_domain; + TempNewSymbol parsed_name = NULL; + result = parser.parseClassFile(h_name, + loader_data, + protection_domain, + parsed_name, + false, + CHECK_(h)); + } // end of timer // add to package table if (add_package(name, classpath_index, THREAD)) { h = result; @@ -974,12 +1191,19 @@ NEWPERFTICKCOUNTER(_perf_sys_class_lookup_time, SUN_CLS, "lookupSysClassTime"); NEWPERFTICKCOUNTER(_perf_shared_classload_time, SUN_CLS, "sharedClassLoadTime"); NEWPERFTICKCOUNTER(_perf_sys_classload_time, SUN_CLS, "sysClassLoadTime"); + NEWPERFTICKCOUNTER(_perf_sys_classload_selftime, SUN_CLS, "sysClassLoadTime.self"); + NEWPERFEVENTCOUNTER(_perf_sys_classload_count, SUN_CLS, "sysClassLoadCount"); + NEWPERFTICKCOUNTER(_perf_app_classload_time, SUN_CLS, "appClassLoadTime"); NEWPERFTICKCOUNTER(_perf_app_classload_selftime, SUN_CLS, "appClassLoadTime.self"); NEWPERFEVENTCOUNTER(_perf_app_classload_count, SUN_CLS, "appClassLoadCount"); + NEWPERFTICKCOUNTER(_perf_define_appclasses, SUN_CLS, "defineAppClasses"); NEWPERFTICKCOUNTER(_perf_define_appclass_time, SUN_CLS, "defineAppClassTime"); NEWPERFTICKCOUNTER(_perf_define_appclass_selftime, SUN_CLS, "defineAppClassTime.self"); + NEWPERFTICKCOUNTER(_perf_define_sysclasses, SUN_CLS, "defineSysClasses"); + NEWPERFTICKCOUNTER(_perf_define_sysclass_time, SUN_CLS, "defineSysClassTime"); + NEWPERFTICKCOUNTER(_perf_define_sysclass_selftime, SUN_CLS, "defineSysClassTime.self"); NEWPERFBYTECOUNTER(_perf_app_classfile_bytes_read, SUN_CLS, "appClassBytes"); NEWPERFBYTECOUNTER(_perf_sys_classfile_bytes_read, SUN_CLS, "sysClassBytes"); @@ -1014,19 +1238,31 @@ if (UnsyncloadClass) { _isUnsyncloadClass->inc(); } + NEWPERFEVENTCOUNTER(_perf_getstackacc_count, SUN_CLS, "getStackACCCount"); + NEWPERFEVENTCOUNTER(_perf_getstackacc_frames_count, SUN_CLS, "getStackACCFrames"); + NEWPERFEVENTCOUNTER(_perf_getstackacc_priv_count, SUN_CLS, "getStackACCPrivFound"); + NEWPERFEVENTCOUNTER(_perf_getstackacc_newacc_count, SUN_CLS, "getStackACCNewACCCount"); } - // lookup zip library entry points + // lookup zip library entry points, note libjava.dll also counts on zip library for modules load_zip_library(); // initialize search path setup_bootstrap_search_path(); + + // If we have already committed to a module native library, load it + if (UseModuleNativeLibs && Arguments::has_module_image()) { + // lookup module loader entry points for module mode + load_module_search_library(); + // No need for meta-index with module library + LazyBootClassLoader = false; + } + if (LazyBootClassLoader) { // set up meta index which makes boot classpath initialization lazier setup_meta_index(); } } - jlong ClassLoader::classloader_time_ms() { return UsePerfData ? Management::ticks_to_ms(_perf_accumulated_time->get_value()) : -1;
--- a/src/share/vm/classfile/classLoader.hpp Fri Apr 26 00:29:12 2013 -0700 +++ b/src/share/vm/classfile/classLoader.hpp Tue May 07 17:14:42 2013 -0700 @@ -167,12 +167,17 @@ static PerfCounter* _perf_sys_class_lookup_time; static PerfCounter* _perf_shared_classload_time; static PerfCounter* _perf_sys_classload_time; + static PerfCounter* _perf_sys_classload_selftime; + static PerfCounter* _perf_sys_classload_count; static PerfCounter* _perf_app_classload_time; static PerfCounter* _perf_app_classload_selftime; static PerfCounter* _perf_app_classload_count; static PerfCounter* _perf_define_appclasses; static PerfCounter* _perf_define_appclass_time; static PerfCounter* _perf_define_appclass_selftime; + static PerfCounter* _perf_define_sysclasses; + static PerfCounter* _perf_define_sysclass_time; + static PerfCounter* _perf_define_sysclass_selftime; static PerfCounter* _perf_app_classfile_bytes_read; static PerfCounter* _perf_sys_classfile_bytes_read; @@ -182,6 +187,11 @@ static PerfCounter* _sync_JVMDefineClassLockFreeCounter; static PerfCounter* _sync_JNIDefineClassLockFreeCounter; + static PerfCounter* _perf_getstackacc_count; + static PerfCounter* _perf_getstackacc_frames_count; + static PerfCounter* _perf_getstackacc_priv_count; + static PerfCounter* _perf_getstackacc_newacc_count; + static PerfCounter* _unsafe_defineClassCallCounter; static PerfCounter* _isUnsyncloadClass; static PerfCounter* _load_instance_class_failCounter; @@ -193,6 +203,9 @@ // Hash table used to keep track of loaded packages static PackageHashtable* _package_hash_table; static const char* _shared_archive; + // For module library loading + static void* _base_context; + static char* _libpath; // Hash function static unsigned int hash(const char *s, int n); @@ -207,14 +220,21 @@ static void setup_meta_index(); static void setup_bootstrap_search_path(); static void load_zip_library(); + static void load_module_search_library(); static void create_class_path_entry(char *path, struct stat st, ClassPathEntry **new_entry, bool lazy); // Canonicalizes path names, so strcmp will work properly. This is mainly // to avoid confusing the zip library static bool get_canonical_path(char* orig, char* out, int len); + + // Load individual .class file from a module library + static instanceKlassHandle load_class_from_module_library(Symbol* h_name, TRAPS); + // Load individual .class file from classpath + static instanceKlassHandle load_class_from_classpath(Symbol* h_name, int start, int end, TRAPS); + public: - // Used by the kernel jvm. - static void update_class_path_entry_list(const char *path, + // Used by the kernel jvm, and by Jigsaw via JVM_ExtendBootClassPath + static bool update_class_path_entry_list(const char *path, bool check_for_duplicates); static void print_bootclasspath(); @@ -237,11 +257,20 @@ static PerfCounter* perf_app_classload_time() { return _perf_app_classload_time; } static PerfCounter* perf_app_classload_selftime() { return _perf_app_classload_selftime; } static PerfCounter* perf_app_classload_count() { return _perf_app_classload_count; } + static PerfCounter* perf_sys_classload_selftime() { return _perf_sys_classload_selftime; } + static PerfCounter* perf_sys_classload_count() { return _perf_sys_classload_count; } static PerfCounter* perf_define_appclasses() { return _perf_define_appclasses; } static PerfCounter* perf_define_appclass_time() { return _perf_define_appclass_time; } static PerfCounter* perf_define_appclass_selftime() { return _perf_define_appclass_selftime; } + static PerfCounter* perf_define_sysclasses() { return _perf_define_sysclasses; } + static PerfCounter* perf_define_sysclass_time() { return _perf_define_sysclass_time; } + static PerfCounter* perf_define_sysclass_selftime() { return _perf_define_sysclass_selftime; } static PerfCounter* perf_app_classfile_bytes_read() { return _perf_app_classfile_bytes_read; } static PerfCounter* perf_sys_classfile_bytes_read() { return _perf_sys_classfile_bytes_read; } + static PerfCounter* perf_getstackacc_count() { return _perf_getstackacc_count; } + static PerfCounter* perf_getstackacc_priv_count() { return _perf_getstackacc_priv_count; } + static PerfCounter* perf_getstackacc_frames_count() { return _perf_getstackacc_frames_count; } + static PerfCounter* perf_getstackacc_newacc_count() { return _perf_getstackacc_newacc_count; } // Record how often system loader lock object is contended static PerfCounter* sync_systemLoaderLockContentionRate() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/classfile/jigsaw.h Tue May 07 17:14:42 2013 -0700 @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef JIGSAW_H +#define JIGSAW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Jigsaw native interface called by the VM. + * + */ + +typedef struct { + const char* module_name; + const char* module_version; + const char* libpath; + const char* source; +} jmodule; + +#define JIGSAW_ERROR_INVALID_MODULE_LIBRARY 101 +#define JIGSAW_ERROR_BAD_FILE_HEADER 102 +#define JIGSAW_ERROR_BAD_CONFIG 103 +#define JIGSAW_ERROR_OPEN_CONFIG 104 +#define JIGSAW_ERROR_OPEN_MODULE_INFO 105 +#define JIGSAW_ERROR_BAD_MODULE_INFO 106 +#define JIGSAW_ERROR_INVALID_MODULE 107 +#define JIGSAW_ERROR_INVALID_CONTEXT 108 +#define JIGSAW_ERROR_MODULE_LIBRARY_NOT_FOUND 109 +#define JIGSAW_ERROR_CONTEXTS_NOT_LOADED 110 +#define JIGSAW_ERROR_MODULE_NOT_FOUND 111 +#define JIGSAW_ERROR_BASE_MODULE_NOT_FOUND 112 +#define JIGSAW_ERROR_CLASS_NOT_FOUND 113 +#define JIGSAW_ERROR_READ_CLASS_ENTRY 114 +#define JIGSAW_ERROR_INVALID_MODULE_IDS 116 +#define JIGSAW_ERROR_ZIP_LIBRARY_NOT_FOUND 201 +#define JIGSAW_ERROR_BUFFER_TOO_SHORT 202 + +/* + * Return the path of the default system module library of the given java_home. + * This method returns 0 if succeed; otherwise returns non-zero error code. + + * java_home : JAVA_HOME + * libpath : allocated buffer to be set with the path + * of the system module library + * len : length of the allocated libpath buffer + */ +typedef jint +(*get_system_module_library_fn_t)(const char *java_home, + char *libpath, + size_t len); + +/* + * Load the contexts of a given module query and set the + * *context to the context containing the base module. + * This method returns 0 if succeed; otherwise returns non-zero + * error code. + * + * libpath : module library path (must be non-NULL) + * modulepath : module path or NULL + * module_query : module query in module mode or NULL in classpath mode + * context : To be set with the handle to the context containing + * the base module. The returned context can contain + * one or more modules that are required to be loaded + * by the VM bootstrap class loader. + */ +typedef jint +(*load_module_context_fn_t)(const char *libpath, const char *modulepath, + const char *module_query, + void **context); + +/* + * Finds the class of a given classname local in a given context + * This method returns 0 if the class is found; otherwise returns + * non-zero error code. + * + * context : handle to the context + * classname : fully-qualified class name (in UTF8 format) + * module : handle to the module containing the class + * len : length of the class data + */ +typedef jint +(*find_local_module_class_fn_t)(void *context, + const char *classname, + void **module, + jint *len); + +/* + * Reads bytestream of a given classname local in a given module + * This method returns 0 if succeed; otherwise returns non-zero + * error code. + * + * module : handle to the module containing the class + * classname : fully-qualified class name (in UTF8 format) + * buf : an allocated buffer to store the class data + * len : length of the buffer + */ +typedef jint +(*read_local_module_class_fn_t)(void *module, + const char *classname, + unsigned char *buf, + jint size); + +/* + * Get the information about the given module. + * + * module : handle to a module + * minfo : a pointer to struct for the module information. + */ +typedef jint (*get_module_info_fn_t)(void *module, + jmodule *minfo); + +/* + * Called by Java_org_openjdk_jigsaw_ClassPathContext_initBootstrapContexts + */ +void init_bootstrap_contexts(const char** non_bootstrap_modules, jint len); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* JIGSAW_H */
--- a/src/share/vm/classfile/systemDictionary.cpp Fri Apr 26 00:29:12 2013 -0700 +++ b/src/share/vm/classfile/systemDictionary.cpp Tue May 07 17:14:42 2013 -0700 @@ -46,6 +46,7 @@ #include "oops/typeArrayKlass.hpp" #include "prims/jvmtiEnvBase.hpp" #include "prims/methodHandles.hpp" +#include "runtime/arguments.hpp" #include "runtime/biasedLocking.hpp" #include "runtime/fieldType.hpp" #include "runtime/handles.inline.hpp" @@ -78,6 +79,7 @@ Klass* SystemDictionary::_box_klasses[T_VOID+1] = { NULL /*, NULL...*/ }; oop SystemDictionary::_java_system_loader = NULL; +oop SystemDictionary::_java_base_module_loader = NULL; bool SystemDictionary::_has_loadClassInternal = false; bool SystemDictionary::_has_checkPackageAccess = false; @@ -87,7 +89,7 @@ // ---------------------------------------------------------------------------- -// Java-level SystemLoader +// Java-level SystemLoader == application loader == launcher loader for entrypoint oop SystemDictionary::java_system_loader() { return _java_system_loader; @@ -105,6 +107,40 @@ _java_system_loader = (oop)result.get_jobject(); } +// ---------------------------------------------------------------------------- +// Java-level boot loader for base module +// Today: set for running modular_app both to delegate up to, +// and to translate to null inside vm +// If running a non-modular app, this is set to null +// If this changes, change JDK_GetModuleLoader + +oop SystemDictionary::java_base_module_loader() { + return _java_base_module_loader; +} + +void SystemDictionary::compute_java_base_module_loader(TRAPS) { + if (!UseModuleBootLoader) return; + if (!Arguments::running_modular_app()) return; + + // The base module loader should already be loaded by now by the real null loader + Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::org_openjdk_jigsaw_BootLoader(), + Handle(), Handle(), true, THREAD); + if (!HAS_PENDING_EXCEPTION && k != NULL) { + instanceKlassHandle ik(THREAD, k); + JavaValue result(T_OBJECT); + JavaCalls::call_static(&result, + ik, + vmSymbols::getBaseModuleLoader_name(), + vmSymbols::void_module_bootloader_signature(), + THREAD); + if (HAS_PENDING_EXCEPTION) { + UseModuleBootLoader = false; + CLEAR_PENDING_EXCEPTION; + } else { + _java_base_module_loader = (oop)result.get_jobject(); + } + } +} ClassLoaderData* SystemDictionary::register_loader(Handle class_loader, TRAPS) { if (class_loader() == NULL) return ClassLoaderData::the_null_class_loader_data(); @@ -1096,26 +1132,30 @@ verify, THREAD); - const char* pkg = "java/"; - if (!HAS_PENDING_EXCEPTION && - !class_loader.is_null() && - parsed_name != NULL && - !strncmp((const char*)parsed_name->bytes(), pkg, strlen(pkg))) { - // It is illegal to define classes in the "java." package from - // JVM_DefineClass or jni_DefineClass unless you're the bootclassloader - ResourceMark rm(THREAD); - char* name = parsed_name->as_C_string(); - char* index = strrchr(name, '/'); - *index = '\0'; // chop to just the package name - while ((index = strchr(name, '/')) != NULL) { - *index = '.'; // replace '/' with '.' in package name +// For modular applications disable this check for now until there is a way to handle +// non-null platform module loaders + if (!Arguments::running_modular_app()) { + const char* pkg = "java/"; + if (!HAS_PENDING_EXCEPTION && + !class_loader.is_null() && + parsed_name != NULL && + !strncmp((const char*)parsed_name->bytes(), pkg, strlen(pkg))) { + // It is illegal to define classes in the "java." package from + // JVM_DefineClass or jni_DefineClass unless you're the bootclassloader + ResourceMark rm(THREAD); + char* name = parsed_name->as_C_string(); + char* index = strrchr(name, '/'); + *index = '\0'; // chop to just the package name + while ((index = strchr(name, '/')) != NULL) { + *index = '.'; // replace '/' with '.' in package name + } + const char* fmt = "Prohibited package name: %s"; + size_t len = strlen(fmt) + strlen(name); + char* message = NEW_RESOURCE_ARRAY(char, len); + jio_snprintf(message, len, fmt, name); + Exceptions::_throw_msg(THREAD_AND_LOCATION, + vmSymbols::java_lang_SecurityException(), message); } - const char* fmt = "Prohibited package name: %s"; - size_t len = strlen(fmt) + strlen(name); - char* message = NEW_RESOURCE_ARRAY(char, len); - jio_snprintf(message, len, fmt, name); - Exceptions::_throw_msg(THREAD_AND_LOCATION, - vmSymbols::java_lang_SecurityException(), message); } if (!HAS_PENDING_EXCEPTION) { @@ -1266,36 +1306,72 @@ } } -instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) { +instanceKlassHandle SystemDictionary::load_local_instance_class(Symbol* class_name, Handle class_loader, TRAPS) { + + assert(class_loader.is_null(), "only local load for null classloader"); + assert(THREAD->is_Java_thread(), "must be a JavaThread"); + instanceKlassHandle nh = instanceKlassHandle(); // null Handle - if (class_loader.is_null()) { - - // Search the shared system dictionary for classes preloaded into the - // shared spaces. - instanceKlassHandle k; - { - PerfTraceTime vmtimer(ClassLoader::perf_shared_classload_time()); - k = load_shared_class(class_name, class_loader, THREAD); + JavaThread* jt = (JavaThread*) THREAD; + + // Search the shared system dictionary for classes preloaded into the + // shared spaces. + instanceKlassHandle k; + { + PerfTraceTime vmtimer(ClassLoader::perf_shared_classload_time()); + k = load_shared_class(class_name, class_loader, THREAD); + } + + if (k.is_null()) { + // Use VM class loader + PerfClassTraceTime vmtimer(ClassLoader::perf_sys_classload_time(), + ClassLoader::perf_sys_classload_selftime(), + ClassLoader::perf_sys_classload_count(), + jt->get_thread_stat()->perf_recursion_counts_addr(), + jt->get_thread_stat()->perf_timers_addr(), + PerfClassTraceTime::CLASS_LOAD); + k = ClassLoader::load_classfile(class_name, CHECK_(nh)); + } + + // find_or_define_instance_class may return a different instanceKlass + if (!k.is_null()) { + k = find_or_define_instance_class(class_name, class_loader, k, CHECK_(nh)); + } + return k; +} + +instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) { + + instanceKlassHandle k = instanceKlassHandle(); // null Handle + Handle call_class_loader = class_loader; + + if (call_class_loader.is_null()) { + // load using vm bootloader + k = load_local_instance_class(class_name, call_class_loader, THREAD); + + // for module mode, will need to delegate to module Bootloader if vm bootloader + // does not find locally + // TODO: ensure that we don't loop forever + if (k.is_null()) { + if (java_base_module_loader() != NULL) { + call_class_loader = Handle(THREAD, java_base_module_loader()); + } + } else { + return k; } - - if (k.is_null()) { - // Use VM class loader - PerfTraceTime vmtimer(ClassLoader::perf_sys_classload_time()); - k = ClassLoader::load_classfile(class_name, CHECK_(nh)); - } - - // find_or_define_instance_class may return a different InstanceKlass - if (!k.is_null()) { - k = find_or_define_instance_class(class_name, class_loader, k, CHECK_(nh)); - } + } + + if (call_class_loader.is_null()) { return k; } else { - // Use user specified class loader to load class. Call loadClass operation on class_loader. - ResourceMark rm(THREAD); - + + instanceKlassHandle nh = instanceKlassHandle(); // null Handle assert(THREAD->is_Java_thread(), "must be a JavaThread"); JavaThread* jt = (JavaThread*) THREAD; + // Use user specified class loader to load class. Call loadClass operation on call_class_loader. + ResourceMark rm(THREAD); + PerfClassTraceTime vmtimer(ClassLoader::perf_app_classload_time(), ClassLoader::perf_app_classload_selftime(), ClassLoader::perf_app_classload_count(), @@ -1322,7 +1398,7 @@ // not parallelCapable. This was a risky transitional // flag for diagnostic purposes only. It is risky to call // custom class loaders without synchronization. - // WARNING If a custom class loader does NOT synchronizer findClass, or callers of + // WARNING If a custom class loader does NOT synchronize findClass, or callers of // findClass, the UnsyncloadClass flag risks unexpected timing bugs in the field. // Do NOT assume this will be supported in future releases. // @@ -1330,7 +1406,7 @@ // a customer that counts on this call if (MustCallLoadClassInternal && has_loadClassInternal()) { JavaCalls::call_special(&result, - class_loader, + call_class_loader, spec_klass, vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature(), @@ -1338,7 +1414,7 @@ CHECK_(nh)); } else { JavaCalls::call_virtual(&result, - class_loader, + call_class_loader, spec_klass, vmSymbols::loadClass_name(), vmSymbols::string_class_signature(), @@ -1648,6 +1724,7 @@ void SystemDictionary::always_strong_oops_do(OopClosure* blk) { blk->do_oop(&_java_system_loader); blk->do_oop(&_system_loader_lock_obj); + blk->do_oop(&_java_base_module_loader); dictionary()->always_strong_oops_do(blk); @@ -1695,6 +1772,7 @@ void SystemDictionary::oops_do(OopClosure* f) { f->do_oop(&_java_system_loader); f->do_oop(&_system_loader_lock_obj); + f->do_oop(&_java_base_module_loader); // Adjust dictionary dictionary()->oops_do(f);
--- a/src/share/vm/classfile/systemDictionary.hpp Fri Apr 26 00:29:12 2013 -0700 +++ b/src/share/vm/classfile/systemDictionary.hpp Tue May 07 17:14:42 2013 -0700 @@ -464,11 +464,16 @@ static bool Object_klass_loaded() { return WK_KLASS(Object_klass) != NULL; } static bool ClassLoader_klass_loaded() { return WK_KLASS(ClassLoader_klass) != NULL; } - // Returns default system loader + // Returns default system loader == application loader == launcher loader for entrypoint static oop java_system_loader(); + // Returns module loader for jdk base module + static oop java_base_module_loader(); + // Compute the default system loader static void compute_java_system_loader(TRAPS); + // Compute the module loader for jdk base module + static void compute_java_base_module_loader(TRAPS); // Register a new class loader static ClassLoaderData* register_loader(Handle class_loader, TRAPS); @@ -625,6 +630,7 @@ Handle class_loader, TRAPS); static void clean_up_shared_class(instanceKlassHandle ik, Handle class_loader, TRAPS); static instanceKlassHandle load_instance_class(Symbol* class_name, Handle class_loader, TRAPS); + static instanceKlassHandle load_local_instance_class(Symbol* class_name, Handle class_loader, TRAPS); static Handle compute_loader_lock_object(Handle class_loader, TRAPS); static void check_loader_lock_contention(Handle loader_lock, TRAPS); static bool is_parallelCapable(Handle class_loader); @@ -692,6 +698,7 @@ static Klass* _box_klasses[T_VOID+1]; static oop _java_system_loader; + static oop _java_base_module_loader; static bool _has_loadClassInternal; static bool _has_checkPackageAccess;
--- a/src/share/vm/classfile/verifier.cpp Fri Apr 26 00:29:12 2013 -0700 +++ b/src/share/vm/classfile/verifier.cpp Tue May 07 17:14:42 2013 -0700 @@ -44,6 +44,7 @@ #include "runtime/interfaceSupport.hpp" #include "runtime/javaCalls.hpp" #include "runtime/orderAccess.hpp" +#include "services/threadService.hpp" #include "runtime/os.hpp" #ifdef TARGET_ARCH_x86 # include "bytes_x86.hpp" @@ -128,6 +129,19 @@ if (TraceClassInitialization) { tty->print_cr("Start class verification for: %s", klassName); } + + assert(THREAD->is_Java_thread(), "non-JavaThread in verifier"); + JavaThread* jt = (JavaThread*)THREAD; + + // Timer includes any side effects of class verification (resolution, + // etc), but not recursive entry into verify_code(). + PerfClassTraceTime timer(ClassLoader::perf_class_verify_time(), + ClassLoader::perf_class_verify_selftime(), + ClassLoader::perf_classes_verified(), + jt->get_thread_stat()->perf_recursion_counts_addr(), + jt->get_thread_stat()->perf_timers_addr(), + PerfClassTraceTime::CLASS_VERIFY); + if (klass->major_version() >= STACKMAP_ATTRIBUTE_MAJOR_VERSION) { ClassVerifier split_verifier(klass, THREAD); split_verifier.verify_class(THREAD);
--- a/src/share/vm/classfile/vmSymbols.hpp Fri Apr 26 00:29:12 2013 -0700 +++ b/src/share/vm/classfile/vmSymbols.hpp Tue May 07 17:14:42 2013 -0700 @@ -111,6 +111,7 @@ template(java_lang_AssertionStatusDirectives, "java/lang/AssertionStatusDirectives") \ template(getBootClassPathEntryForClass_name, "getBootClassPathEntryForClass") \ template(sun_misc_PostVMInitHook, "sun/misc/PostVMInitHook") \ + template(org_openjdk_jigsaw_BootLoader, "org/openjdk/jigsaw/BootLoader") \ template(sun_misc_Launcher_ExtClassLoader, "sun/misc/Launcher$ExtClassLoader") \ \ /* Java runtime version access */ \ @@ -335,6 +336,7 @@ template(getFromClass_name, "getFromClass") \ template(dispatch_name, "dispatch") \ template(getSystemClassLoader_name, "getSystemClassLoader") \ + template(getBaseModuleLoader_name, "getBaseModuleLoader") \ template(fillInStackTrace_name, "fillInStackTrace") \ template(fillInStackTrace0_name, "fillInStackTrace0") \ template(getCause_name, "getCause") \ @@ -465,6 +467,7 @@ template(int_int_void_signature, "(II)V") \ template(long_long_void_signature, "(JJ)V") \ template(void_classloader_signature, "()Ljava/lang/ClassLoader;") \ + template(void_module_bootloader_signature, "()Lorg/openjdk/jigsaw/BootLoader;") \ template(void_object_signature, "()Ljava/lang/Object;") \ template(void_class_signature, "()Ljava/lang/Class;") \ template(void_class_array_signature, "()[Ljava/lang/Class;") \
--- a/src/share/vm/oops/instanceKlass.cpp Fri Apr 26 00:29:12 2013 -0700 +++ b/src/share/vm/oops/instanceKlass.cpp Tue May 07 17:14:42 2013 -0700 @@ -626,19 +626,9 @@ if (!this_oop->is_linked()) { if (!this_oop->is_rewritten()) { - { - // Timer includes any side effects of class verification (resolution, - // etc), but not recursive entry into verify_code(). - PerfClassTraceTime timer(ClassLoader::perf_class_verify_time(), - ClassLoader::perf_class_verify_selftime(), - ClassLoader::perf_classes_verified(), - jt->get_thread_stat()->perf_recursion_counts_addr(), - jt->get_thread_stat()->perf_timers_addr(), - PerfClassTraceTime::CLASS_VERIFY); - bool verify_ok = verify_code(this_oop, throw_verifyerror, THREAD); - if (!verify_ok) { - return false; - } + bool verify_ok = verify_code(this_oop, throw_verifyerror, THREAD); + if (!verify_ok) { + return false; } // Just in case a side-effect of verify linked this class already
--- a/src/share/vm/prims/jni.cpp Fri Apr 26 00:29:12 2013 -0700 +++ b/src/share/vm/prims/jni.cpp Tue May 07 17:14:42 2013 -0700 @@ -394,7 +394,11 @@ } ResourceMark rm(THREAD); ClassFileStream st((u1*) buf, bufLen, NULL); - Handle class_loader (THREAD, JNIHandles::resolve(loaderRef)); + + oop local_loader = JNIHandles::resolve(loaderRef); + oop null_loader = NULL; + local_loader = (local_loader == SystemDictionary::java_base_module_loader() ? null_loader : local_loader); + Handle class_loader(THREAD, local_loader); if (UsePerfData && !class_loader.is_null()) { // check whether the current caller thread holds the lock or not.
--- a/src/share/vm/prims/jvm.cpp Fri Apr 26 00:29:12 2013 -0700 +++ b/src/share/vm/prims/jvm.cpp Tue May 07 17:14:42 2013 -0700 @@ -793,7 +793,10 @@ } } TempNewSymbol h_name = SymbolTable::new_symbol(name, CHECK_NULL); - Handle h_loader(THREAD, JNIHandles::resolve(loader)); + oop local_loader = JNIHandles::resolve(loader); + oop null_loader = NULL; + local_loader = (local_loader == SystemDictionary::java_base_module_loader() ? null_loader : local_loader); + Handle h_loader(THREAD, local_loader); jclass result = find_class_from_class_loader(env, h_name, init, h_loader, Handle(), throwError, THREAD); @@ -875,10 +878,6 @@ jt->get_thread_stat()->perf_timers_addr(), PerfClassTraceTime::DEFINE_CLASS); - if (UsePerfData) { - ClassLoader::perf_app_classfile_bytes_read()->inc(len); - } - // Since exceptions can be thrown, class initialization can take place // if name is NULL no check for class name in .class stream has to be made. TempNewSymbol class_name = NULL; @@ -894,8 +893,17 @@ ResourceMark rm(THREAD); ClassFileStream st((u1*) buf, len, (char *)source); - Handle class_loader (THREAD, JNIHandles::resolve(loader)); + oop local_loader = JNIHandles::resolve(loader); + oop null_loader = NULL; + local_loader = (local_loader == SystemDictionary::java_base_module_loader() ? null_loader : local_loader); + Handle class_loader(THREAD, local_loader); + if (UsePerfData) { + if (loader == NULL) { + ClassLoader::perf_sys_classfile_bytes_read()->inc(len); + } else { + ClassLoader::perf_app_classfile_bytes_read()->inc(len); + } is_lock_held_by_thread(class_loader, ClassLoader::sync_JVMDefineClassLockFreeCounter(), THREAD); @@ -958,7 +966,10 @@ // Security Note: // The Java level wrapper will perform the necessary security check allowing // us to pass the NULL as the initiating class loader. - Handle h_loader(THREAD, JNIHandles::resolve(loader)); + oop local_loader = JNIHandles::resolve(loader); + oop null_loader = NULL; + local_loader = (local_loader == SystemDictionary::java_base_module_loader() ? null_loader : local_loader); + Handle h_loader(THREAD, local_loader); if (UsePerfData) { is_lock_held_by_thread(h_loader, ClassLoader::sync_JVMFindLoadedClassLockFreeCounter(), @@ -974,6 +985,17 @@ (jclass) JNIHandles::make_local(env, k->java_mirror()); JVM_END +JVM_ENTRY(void, JVM_ExtendBootClassPath(JNIEnv *env, const char *path)) + JVMWrapper2("JVM_ExtendBootClassPath(%s)", path); + { + // cf. SystemDictionary::download_and_retry_class_load + HandleMark hm(THREAD); + ResourceMark rm(THREAD); + Handle loader_lock(THREAD, SystemDictionary::system_loader_lock()); + ObjectLocker ol(loader_lock, THREAD); + ClassLoader::update_class_path_entry_list(path, true); + } +JVM_END // Reflection support ////////////////////////////////////////////////////////////////////////////// @@ -1047,6 +1069,21 @@ return JNIHandles::make_local(env, loader); JVM_END +JVM_ENTRY(jobject, JVM_GetModuleLoader(JNIEnv *env, jclass cls)) + JVMWrapper("JVM_GetModuleLoader"); + oop loader; + if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) { + loader = NULL; + } else { + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); + loader = k->class_loader(); + } + if (loader == NULL) { + loader = SystemDictionary::java_base_module_loader(); + } + return JNIHandles::make_local(env, loader); +JVM_END + JVM_QUICK_ENTRY(jboolean, JVM_IsInterface(JNIEnv *env, jclass cls)) JVMWrapper("JVM_IsInterface"); @@ -1233,6 +1270,9 @@ JVM_ENTRY(jobject, JVM_GetStackAccessControlContext(JNIEnv *env, jclass cls)) JVMWrapper("JVM_GetStackAccessControlContext"); + if (UsePerfData) { + ClassLoader::perf_getstackacc_count()->inc(); + } if (!UsePrivilegedStack) return NULL; ResourceMark rm(THREAD); @@ -1271,7 +1311,15 @@ previous_protection_domain = protection_domain; } - if (is_privileged) break; + if (is_privileged) { + if (UsePerfData) { + ClassLoader::perf_getstackacc_priv_count()->inc(); + } + break; + } + if (UsePerfData) { + ClassLoader::perf_getstackacc_frames_count()->inc(); + } } @@ -1281,6 +1329,9 @@ if (is_privileged && privileged_context.is_null()) return NULL; oop result = java_security_AccessControlContext::create(objArrayHandle(), is_privileged, privileged_context, CHECK_NULL); + if (UsePerfData) { + ClassLoader::perf_getstackacc_newacc_count()->inc(); + } return JNIHandles::make_local(env, result); } @@ -1294,6 +1345,9 @@ } oop result = java_security_AccessControlContext::create(h_context, is_privileged, privileged_context, CHECK_NULL); + if (UsePerfData) { + ClassLoader::perf_getstackacc_newacc_count()->inc(); + } return JNIHandles::make_local(env, result); JVM_END
--- a/src/share/vm/prims/jvm.h Fri Apr 26 00:29:12 2013 -0700 +++ b/src/share/vm/prims/jvm.h Tue May 07 17:14:42 2013 -0700 @@ -447,6 +447,18 @@ jboolean verify); /* + * Append a path to the boot class path + */ +JNIEXPORT void JNICALL +JVM_ExtendBootClassPath(JNIEnv *env, const char *path); + +/* + * Append a path to the boot class path + */ +JNIEXPORT void JNICALL +JVM_ExtendBootClassPath(JNIEnv *env, const char *path); + +/* * Reflection support functions */ @@ -459,6 +471,12 @@ JNIEXPORT jobject JNICALL JVM_GetClassLoader(JNIEnv *env, jclass cls); +JNIEXPORT jobject JNICALL +JVM_GetModuleLoader(JNIEnv *env, jclass cls); + +JNIEXPORT jobject JNICALL +JVM_GetModuleLoader(JNIEnv *env, jclass cls); + JNIEXPORT jboolean JNICALL JVM_IsInterface(JNIEnv *env, jclass cls);
--- a/src/share/vm/runtime/arguments.cpp Fri Apr 26 00:29:12 2013 -0700 +++ b/src/share/vm/runtime/arguments.cpp Tue May 07 17:14:42 2013 -0700 @@ -65,6 +65,7 @@ char** Arguments::_jvm_args_array = NULL; int Arguments::_num_jvm_args = 0; char* Arguments::_java_command = NULL; +char* Arguments::_java_main = NULL; SystemProperty* Arguments::_system_properties = NULL; const char* Arguments::_gc_log_filename = NULL; bool Arguments::_has_profile = false; @@ -77,6 +78,8 @@ const char* Arguments::_sun_java_launcher = DEFAULT_JAVA_LAUNCHER; int Arguments::_sun_java_launcher_pid = -1; bool Arguments::_created_by_gamma_launcher = false; +const char* Arguments::_sun_java_launcher_module = NULL; +const char* Arguments::_sun_java_launcher_module_library = NULL; // These parameters are reset in method parse_vm_init_args(JavaVMInitArgs*) bool Arguments::_AlwaysCompileLoopMethods = AlwaysCompileLoopMethods; @@ -101,6 +104,11 @@ SystemProperty *Arguments::_java_home = NULL; SystemProperty *Arguments::_java_class_path = NULL; SystemProperty *Arguments::_sun_boot_class_path = NULL; +SystemProperty *Arguments::_sun_boot_class_prepend_path = NULL; +SystemProperty *Arguments::_sun_boot_class_append_path = NULL; +SystemProperty *Arguments::_sun_boot_module_base = NULL; + +int Arguments::_boot_module_index = 0; char* Arguments::_meta_index_path = NULL; char* Arguments::_meta_index_dir = NULL; @@ -141,6 +149,14 @@ _sun_java_launcher_pid = atoi(tail); continue; } + if (match_option(option, "-Dsun.java.launcher.module.library=", &tail)) { + _sun_java_launcher_module_library = strdup(tail); + continue; + } + if (match_option(option, "-Dsun.java.launcher.module=", &tail)) { + _sun_java_launcher_module = strdup(tail); + continue; + } } } @@ -162,6 +178,9 @@ _java_library_path = new SystemProperty("java.library.path", NULL, true); _java_home = new SystemProperty("java.home", NULL, true); _sun_boot_class_path = new SystemProperty("sun.boot.class.path", NULL, true); + _sun_boot_class_prepend_path = new SystemProperty("sun.boot.class.prepend.path", NULL, true); + _sun_boot_class_append_path = new SystemProperty("sun.boot.class.append.path", NULL, true); + _sun_boot_module_base = new SystemProperty("sun.boot.module.classpath", NULL, true); _java_class_path = new SystemProperty("java.class.path", "", true); @@ -173,6 +192,9 @@ PropertyList_add(&_system_properties, _java_home); PropertyList_add(&_system_properties, _java_class_path); PropertyList_add(&_system_properties, _sun_boot_class_path); + PropertyList_add(&_system_properties, _sun_boot_class_prepend_path); + PropertyList_add(&_system_properties, _sun_boot_class_append_path); + PropertyList_add(&_system_properties, _sun_boot_module_base); // Set OS specific system properties values os::init_system_properties_values(); @@ -315,6 +337,7 @@ inline void add_suffix_to_prefix(const char* suffix); inline void add_suffix(const char* suffix); inline void reset_path(const char* base); + inline void reset_base(const char* base); // Expand the jar/zip files in each directory listed by the java.endorsed.dirs // property. Must be called after all command-line arguments have been @@ -326,10 +349,17 @@ inline const char* get_prefix() const { return _items[_scp_prefix]; } inline const char* get_suffix() const { return _items[_scp_suffix]; } inline const char* get_endorsed() const { return _items[_scp_endorsed]; } + inline bool scp_path_reset() const { return _scp_path_reset; } // Combine all the components into a single c-heap-allocated string; caller // must free the string if/when no longer needed. char* combined_path(); + char* combined_path_helper(int start, int count); + + // For jdk module image,, split bootclasspath into prepend path, base module and append path + // Retain sun.boot.class.path with full path including module image + char* combined_prepend_path(); + char* combined_append_path(); private: // Utility routines. @@ -340,13 +370,16 @@ // Array indices for the items that make up the sysclasspath. All except the // base are allocated in the C heap and freed by this class. + // If anything is added here, must change combined_prepend_path enum { _scp_prefix, // from -Xbootclasspath/p:... _scp_endorsed, // the expansion of -Djava.endorsed.dirs=... - _scp_base, // the default sysclasspath + _scp_base, // the default sysclasspath, -Xbootclasspath override _scp_suffix, // from -Xbootclasspath/a:... _scp_nitems // the number of items, must be last. }; + bool _scp_path_reset; // whether -Xbootclasspath reset entire path + // if reset, then sun_boot_module_base is reset to NULL const char* _items[_scp_nitems]; DEBUG_ONLY(bool _expansion_done;) @@ -355,6 +388,7 @@ SysClassPath::SysClassPath(const char* base) { memset(_items, 0, sizeof(_items)); _items[_scp_base] = base; + _scp_path_reset = false; DEBUG_ONLY(_expansion_done = false;) } @@ -382,6 +416,7 @@ _items[_scp_suffix] = add_to_path(_items[_scp_suffix], suffix, false); } +// Do not allow freeing of _scp_base, because string is shared by _sun_boot_class_path inline void SysClassPath::reset_item_at(int index) { assert(index < _scp_nitems && index != _scp_base, "just checking"); if (_items[index] != NULL) { @@ -395,6 +430,8 @@ reset_item_at(_scp_prefix); reset_item_at(_scp_suffix); set_base(base); + _scp_path_reset = true; + } //------------------------------------------------------------------------------ @@ -429,42 +466,68 @@ DEBUG_ONLY(_expansion_done = true;) } -// Combine the bootclasspath elements, some of which may be null, into a single -// c-heap-allocated string. -char* SysClassPath::combined_path() { - assert(_items[_scp_base] != NULL, "empty default sysclasspath"); - assert(_expansion_done, "must call expand_endorsed() first."); - +// create a string from components, starting at start for nitems +char* SysClassPath::combined_path_helper(int start, int nitems) { size_t lengths[_scp_nitems]; size_t total_len = 0; + int end = start + nitems; + char *cp = NULL; const char separator = *os::path_separator(); // Get the lengths. int i; - for (i = 0; i < _scp_nitems; ++i) { + for (i = start; i < end; ++i) { if (_items[i] != NULL) { lengths[i] = strlen(_items[i]); // Include space for the separator char (or a NULL for the last item). total_len += lengths[i] + 1; } } - assert(total_len > 0, "empty sysclasspath not allowed"); - - // Copy the _items to a single string. - char* cp = NEW_C_HEAP_ARRAY(char, total_len, mtInternal); - char* cp_tmp = cp; - for (i = 0; i < _scp_nitems; ++i) { - if (_items[i] != NULL) { - memcpy(cp_tmp, _items[i], lengths[i]); - cp_tmp += lengths[i]; - *cp_tmp++ = separator; + + if (total_len > 0) { + // Copy the _items to a single string. + cp = NEW_C_HEAP_ARRAY(char, total_len, mtInternal); + char* cp_tmp = cp; + for (i = start; i < end; ++i) { + if (_items[i] != NULL) { + memcpy(cp_tmp, _items[i], lengths[i]); + cp_tmp += lengths[i]; + *cp_tmp++ = separator; + } } + *--cp_tmp = '\0'; // Replace the extra separator. } - *--cp_tmp = '\0'; // Replace the extra separator. return cp; } +// Combine the bootclasspath elements, some of which may be null, into a single +// c-heap-allocated string. +char* SysClassPath::combined_path() { + if (!UseModuleNativeLibs) { + assert(_items[_scp_base] != NULL, "empty default sysclasspath"); + } + assert(_expansion_done, "must call expand_endorsed() first."); + + return combined_path_helper(0, _scp_nitems); +} + +// Combine the bootclasspath elements before the default jdk modules,some of which may be null, +// into a single c-heap-allocated string for jdk library searching +char* SysClassPath::combined_prepend_path() { + assert(_expansion_done, "must call expand_endorsed() first."); + + // If explicit -Xbootclasspath, then we do not search the module library + int nprepend = _scp_base; + return combined_path_helper(0, nprepend); +} + +// Combine the bootclasspath elements after the default jdk modules,some of which may be null, +// into a single c-heap-allocated string for jdk library searching +char* SysClassPath::combined_append_path() { + return combined_path_helper(_scp_suffix, 1); +} + // Note: path must be c-heap-allocated (or NULL); it is freed if non-null. char* SysClassPath::add_to_path(const char* path, const char* str, bool prepend) { @@ -976,6 +1039,12 @@ _java_command = value; // Record value in Arguments, but let it get passed to Java. + } else if (strcmp(key, "sun.java.main") == 0) { + _java_main = value; + + // don't add this property to the properties exposed to the java application + FreeHeap(key); + return true; } else if (strcmp(key, "sun.java.launcher.pid") == 0) { // launcher.pid property is private and is processed // in process_sun_java_launcher_properties(); @@ -2239,6 +2308,7 @@ if (!match_option(option, "-Djava.class.path", &tail) && !match_option(option, "-Dsun.java.command", &tail) && + !match_option(option, "-Dsun.java.main", &tail) && !match_option(option, "-Dsun.java.launcher", &tail)) { // add all jvm options to the jvm_args string. This string @@ -2276,14 +2346,32 @@ JavaAssertions::setSystemClassDefault(enable); // -bootclasspath: } else if (match_option(option, "-Xbootclasspath:", &tail)) { + if (running_modular_app()) { + jio_fprintf(defaultStream::error_stream(), + "-Xbootclasspath: option is not supported for modular applications\n"); + return JNI_EINVAL; + } + scp_p->reset_path(tail); *scp_assembly_required_p = true; // -bootclasspath/a: } else if (match_option(option, "-Xbootclasspath/a:", &tail)) { + if (running_modular_app()) { + jio_fprintf(defaultStream::error_stream(), + "-Xbootclasspath/a: option is not supported for modular applications\n"); + return JNI_EINVAL; + } + scp_p->add_suffix(tail); *scp_assembly_required_p = true; // -bootclasspath/p: } else if (match_option(option, "-Xbootclasspath/p:", &tail)) { + if (running_modular_app()) { + jio_fprintf(defaultStream::error_stream(), + "-Xbootclasspath/p: option is not supported for modular applications\n"); + return JNI_EINVAL; + } + scp_p->add_prefix(tail); *scp_assembly_required_p = true; // -Xrun @@ -2886,9 +2974,34 @@ // This must be done after all -D arguments have been processed. scp_p->expand_endorsed(); + if (UseModuleNativeLibs && has_module_image()) { + if (!scp_p->scp_path_reset()) { + // boot strap class loader will use sysclasspath which combines all of these + char *prepend = scp_p->combined_prepend_path(); + if (prepend != NULL) { + set_prependclasspath(prepend); + } + // do not reset base, do not free existing base, string shared by _sun_boot_class_path + // which will be reset in sys_sysclasspath below + scp_p->set_base(get_boot_module_base()); + scp_assembly_required = true; + + char *append = scp_p->combined_append_path(); + if (append != NULL) { + set_appendclasspath(append); + } + } else { + // overrode bootclasspath, reset these after all command-line args parsed + // default sysclasspath remains + UseModuleNativeLibs = false; + UseModuleBootLoader = false; + _sun_boot_module_base = NULL; // tell JDK we are not using the boot module base + } + } + if (scp_assembly_required || scp_p->get_endorsed() != NULL) { // Assemble the bootclasspath elements into the final path. - Arguments::set_sysclasspath(scp_p->combined_path()); + set_sysclasspath(scp_p->combined_path()); } // This must be done after all arguments have been processed.
--- a/src/share/vm/runtime/arguments.hpp Fri Apr 26 00:29:12 2013 -0700 +++ b/src/share/vm/runtime/arguments.hpp Tue May 07 17:14:42 2013 -0700 @@ -230,6 +230,8 @@ static int _num_jvm_args; // string containing all java command (class/jarfile name and app args) static char* _java_command; + // string containing the module name or the main class name + static char* _java_main; // Property list static SystemProperty* _system_properties; @@ -242,6 +244,12 @@ static SystemProperty *_java_home; static SystemProperty *_java_class_path; static SystemProperty *_sun_boot_class_path; + static SystemProperty *_sun_boot_class_prepend_path; + static SystemProperty *_sun_boot_class_append_path; + static SystemProperty *_sun_boot_module_base; + + // Only valid if using module image + static int _boot_module_index; // Meta-index for knowing what packages are in the boot class path static char* _meta_index_path; @@ -254,6 +262,14 @@ // java/gamma launcher static const char* _sun_java_launcher; + // sun.java.launcher.module, private property identifying + // the module name shared with sun.launcher.LauncherHelper class + static const char* _sun_java_launcher_module; + + // sun.java.launcher.module.library, private property identifying + // the -L module library name shared with sun.launcher.LauncherHelper class + static const char* _sun_java_launcher_module_library; + // sun.java.launcher.pid, private property static int _sun_java_launcher_pid; @@ -433,6 +449,7 @@ static int num_jvm_args() { return _num_jvm_args; } // return the arguments passed to the Java application static const char* java_command() { return _java_command; } + static const char* java_main() { return _java_main; } // print jvm_flags, jvm_args and java_command static void print_on(outputStream* st); @@ -458,6 +475,31 @@ static bool created_by_gamma_launcher(); // -Dsun.java.launcher.pid static int sun_java_launcher_pid() { return _sun_java_launcher_pid; } + // -Dsun.java.launcher.module + static const char* sun_java_launcher_module() { + return _sun_java_launcher_module; + } + // -Dsun.java.launcher.module.library + static const char* sun_java_launcher_module_library() { + return _sun_java_launcher_module_library; + } + + static bool running_modular_app() { + return _sun_java_launcher_module != NULL; + } + + static bool has_module_image() { + return get_boot_module_base() != NULL; + } + + // Note: assumes base module only uses 1 entry in bootclasspath + static int boot_module_index() { + return _boot_module_index; + } + + static void set_boot_module_index(int count) { + _boot_module_index = count; + } // -Xloggc:<file>, if not specified will be NULL static const char* gc_log_filename() { return _gc_log_filename; } @@ -528,6 +570,9 @@ static void set_endorsed_dirs(char *value) { _java_endorsed_dirs->set_value(value); } static void set_sysclasspath(char *value) { _sun_boot_class_path->set_value(value); } static void append_sysclasspath(const char *value) { _sun_boot_class_path->append_value(value); } + static void set_prependclasspath(char *value) { _sun_boot_class_prepend_path->set_value(value); } + static void set_appendclasspath(char *value) { _sun_boot_class_append_path->set_value(value); } + static void set_bootmodulebase(char *value) { _sun_boot_module_base->set_value(value); } static void set_meta_index_path(char* meta_index_path, char* meta_index_dir) { _meta_index_path = meta_index_path; _meta_index_dir = meta_index_dir; @@ -537,6 +582,9 @@ static char *get_dll_dir() { return _sun_boot_library_path->value(); } static char *get_endorsed_dir() { return _java_endorsed_dirs->value(); } static char *get_sysclasspath() { return _sun_boot_class_path->value(); } + static char *get_prependclasspath() { return _sun_boot_class_prepend_path->value(); } + static char *get_appendclasspath() { return _sun_boot_class_append_path->value(); } + static char *get_boot_module_base() { return _sun_boot_module_base->value(); } static char* get_meta_index_path() { return _meta_index_path; } static char* get_meta_index_dir() { return _meta_index_dir; }
--- a/src/share/vm/runtime/globals.hpp Fri Apr 26 00:29:12 2013 -0700 +++ b/src/share/vm/runtime/globals.hpp Tue May 07 17:14:42 2013 -0700 @@ -3627,6 +3627,12 @@ diagnostic(bool, PauseAtExit, false, \ "Pause and wait for keypress on exit if a debugger is attached") \ \ + product(bool, UseModuleNativeLibs, true, \ + "Proto: Load classes using module native libs, assumes true default") \ + \ + product(bool, UseModuleBootLoader, true, \ + "Prototype: Use Module Boot Loader for modular-app class load") \ + \ product(bool, ExtendedDTraceProbes, false, \ "Enable performance-impacting dtrace probes") \ \
--- a/src/share/vm/runtime/os.cpp Fri Apr 26 00:29:12 2013 -0700 +++ b/src/share/vm/runtime/os.cpp Tue May 07 17:14:42 2013 -0700 @@ -1160,6 +1160,7 @@ const char* home = Arguments::get_java_home(); int home_len = (int)strlen(home); + // meta_index_dir is used for AggressiveOpts and white-box testing static const char* meta_index_dir_format = "%/lib/"; static const char* meta_index_format = "%/lib/meta-index"; char* meta_index = format_boot_path(meta_index_format, home, home_len, fileSep, pathSep); @@ -1168,6 +1169,21 @@ if (meta_index_dir == NULL) return false; Arguments::set_meta_index_path(meta_index, meta_index_dir); + // Check if module image on disk + if (UseModuleNativeLibs) { + static const char* jdk_module_image_format = "%/lib/modules/jdk.base"; + char* jdk_base_module = format_boot_path(jdk_module_image_format, home, home_len, fileSep, pathSep); + if (jdk_base_module == NULL) return false; + struct stat st; + if (os::stat(jdk_base_module, &st) == 0) { + // For now fall through so -XX:-UseModuleNativeLibs sees original sysclasspath + Arguments::set_bootmodulebase(jdk_base_module); + } else { + // For now, fall through if no module image + UseModuleNativeLibs = false; + UseModuleBootLoader = false; + } + } // Any modification to the JAR-file list, for the boot classpath must be // aligned with install/install/make/common/Pack.gmk. Note: boot class // path class JARs, are stripped for StackMapTable to reduce download size. @@ -1182,6 +1198,10 @@ #ifdef __APPLE__ "%/lib/JObjC.jar:" #endif + + // ## TEMPORARY hack to keep the legacy launcher working when + // ## only the boot module is installed (cf. j.l.ClassLoader) + "%/lib/modules/jdk.base/8-ea/classes:" "%/classes"; char* sysclasspath = format_boot_path(classpath_format, home, home_len, fileSep, pathSep); if (sysclasspath == NULL) return false;
--- a/src/share/vm/runtime/statSampler.cpp Fri Apr 26 00:29:12 2013 -0700 +++ b/src/share/vm/runtime/statSampler.cpp Tue May 07 17:14:42 2013 -0700 @@ -337,6 +337,32 @@ PerfDataManager::create_string_constant(SUN_RT, "javaCommand", Arguments::java_command(), CHECK); + // only create the sun.rt.javaMain perf counter if java_main is set + // when the VM is launched by the java launcher. + if (Arguments::java_main() != NULL) { + PerfDataManager::create_string_constant(SUN_RT, "javaMain", + Arguments::java_main(), CHECK); + } + + // module name + if (Arguments::sun_java_launcher_module() != NULL) { + PerfDataManager::create_string_constant(SUN_RT, "javaModule", + Arguments::sun_java_launcher_module(), CHECK); + } + + // only create the sun.rt.javaMain perf counter if java_main is set + // when the VM is launched by the java launcher. + if (Arguments::java_main() != NULL) { + PerfDataManager::create_string_constant(SUN_RT, "javaMain", + Arguments::java_main(), CHECK); + } + + // module name + if (Arguments::sun_java_launcher_module() != NULL) { + PerfDataManager::create_string_constant(SUN_RT, "javaModule", + Arguments::sun_java_launcher_module(), CHECK); + } + // the Java VM Internal version string PerfDataManager::create_string_constant(SUN_RT, "internalVersion", VM_Version::internal_vm_info_string(),
--- a/src/share/vm/runtime/thread.cpp Fri Apr 26 00:29:12 2013 -0700 +++ b/src/share/vm/runtime/thread.cpp Tue May 07 17:14:42 2013 -0700 @@ -3607,6 +3607,30 @@ vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); } + // For running a module application today we need to map the java base module loader + // to null on entry to the vm + // We also need to call out to this module loader for classes not found by + // the VM boot loader for the module delegation handling. + // This loader is initialized during InitializeSystemProperties + if (Arguments::running_modular_app()) { + SystemDictionary::compute_java_base_module_loader(THREAD); + if (HAS_PENDING_EXCEPTION) { + vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); + } + } + + // For running a module application today we need to map the java base module loader + // to null on entry to the vm + // We also need to call out to this module loader for classes not found by + // the VM boot loader for the module delegation handling. + // This loader is initialized during InitializeSystemProperties + if (Arguments::running_modular_app()) { + SystemDictionary::compute_java_base_module_loader(THREAD); + if (HAS_PENDING_EXCEPTION) { + vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); + } + } + #if INCLUDE_ALL_GCS // Support for ConcurrentMarkSweep. This should be cleaned up // and better encapsulated. The ugly nested if test would go away
--- a/src/share/vm/utilities/ostream.cpp Fri Apr 26 00:29:12 2013 -0700 +++ b/src/share/vm/utilities/ostream.cpp Tue May 07 17:14:42 2013 -0700 @@ -657,7 +657,9 @@ // Print it as a java-style property list. // System properties don't generally contain newlines, so don't bother with unparsing. for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) { - xs->text()->print_cr("%s=%s", p->key(), p->value()); + if (p->value() != NULL) { + xs->text()->print_cr("%s=%s", p->key(), p->value()); + } } xs->tail("properties"); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/6941923/test6941923.sh Tue May 07 17:14:42 2013 -0700 @@ -0,0 +1,179 @@ +## +## @test @(#)test6941923.sh +## @bug 6941923 +## @summary test new added flags for gc log rotation +## @author yqi +## @run shell test6941923.sh +## + +## skip on windows +OS=`uname -s` +case "$OS" in + SunOS | Linux | Darwin ) + NULL=/dev/null + PS=":" + FS="/" + ;; + Windows_* | CYGWIN_* ) + echo "Test skipped for Windows" + exit 0 + ;; + * ) + echo "Unrecognized system!" + exit 1; + ;; +esac + +if [ "${JAVA_HOME}" = "" ] +then + echo "JAVA_HOME not set" + exit 0 +fi + +$JAVA_HOME/bin/java ${TESTVMOPTS} -version > $NULL 2>&1 + +if [ $? != 0 ]; then + echo "Wrong JAVA_HOME? JAVA_HOME: $JAVA_HOME" + exit $? +fi + +# create a small test case +testname="Test" +if [ -e ${testname}.java ]; then + rm -rf ${testname}.* +fi + +cat >> ${testname}.java << __EOF__ +import java.util.Vector; + +public class Test implements Runnable +{ + private boolean _should_stop = false; + + public static void main(String[] args) throws Exception { + + long limit = Long.parseLong(args[0]) * 60L * 1000L; // minutes + Test t = new Test(); + t.set_stop(false); + Thread thr = new Thread(t); + thr.start(); + + long time1 = System.currentTimeMillis(); + long time2 = System.currentTimeMillis(); + while (time2 - time1 < limit) { + try { + Thread.sleep(2000); // 2 seconds + } + catch(Exception e) {} + time2 = System.currentTimeMillis(); + System.out.print("\r... " + (time2 - time1)/1000 + " seconds"); + } + System.out.println(); + t.set_stop(true); + } + public void set_stop(boolean value) { _should_stop = value; } + public void run() { + int cap = 20000; + int fix_size = 2048; + int loop = 0; + Vector< byte[] > v = new Vector< byte[] >(cap); + while(!_should_stop) { + byte[] g = new byte[fix_size]; + v.add(g); + loop++; + if (loop > cap) { + v = null; + cap *= 2; + if (cap > 80000) cap = 80000; + v = new Vector< byte[] >(cap); + } + } + } +} +__EOF__ + +msgsuccess="succeeded" +msgfail="failed" +gclogsize="16K" +filesize=$((16*1024)) +$JAVA_HOME/bin/javac ${testname}.java > $NULL 2>&1 + +if [ $? != 0 ]; then + echo "$JAVA_HOME/bin/javac ${testname}.java $fail" + exit -1 +fi + +# test for 2 minutes, it will complete circulation of gc log rotation +tts=2 +logfile="test.log" +hotspotlog="hotspot.log" + +if [ -e $logfile ]; then + rm -rf $logfile +fi + +#also delete $hotspotlog if it exists +if [ -f $hotspotlog ]; then + rm -rf $hotspotlog +fi + +options="-Xloggc:$logfile -XX:+UseConcMarkSweepGC -XX:+PrintGC -XX:+PrintGCDetails -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=1 -XX:GCLogFileSize=$gclogsize" +echo "Test gc log rotation in same file, wait for $tts minutes ...." +$JAVA_HOME/bin/java ${TESTVMOPTS} $options $testname $tts +if [ $? != 0 ]; then + echo "$msgfail" + exit -1 +fi + +# rotation file will be $logfile.0 +if [ -f $logfile.0 ]; then + outfilesize=`ls -l $logfile.0 | awk '{print $5 }'` + if [ $((outfilesize)) -ge $((filesize)) ]; then + echo $msgsuccess + else + echo $msgfail + fi +else + echo $msgfail + exit -1 +fi + +# delete log file +rm -rf $logfile.0 +if [ -f $hotspotlog ]; then + rm -rf $hotspotlog +fi + +#multiple log files +numoffiles=3 +options="-Xloggc:$logfile -XX:+UseConcMarkSweepGC -XX:+PrintGC -XX:+PrintGCDetails -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=$numoffiles -XX:GCLogFileSize=$gclogsize" +echo "Test gc log rotation in $numoffiles files, wait for $tts minutes ...." +$JAVA_HOME/bin/java ${TESTVMOPTS} $options $testname $tts +if [ $? != 0 ]; then + echo "$msgfail" + exit -1 +fi + +atleast=0 # at least size of numoffile-1 files >= $gclogsize +tk=0 +while [ $(($tk)) -lt $(($numoffiles)) ] +do + if [ -f $logfile.$tk ]; then + outfilesize=`ls -l $logfile.$tk | awk '{ print $5 }'` + if [ $(($outfilesize)) -ge $(($filesize)) ]; then + atleast=$((atleast+1)) + fi + fi + tk=$((tk+1)) +done + +rm -rf $logfile.* +rm -rf $testname.* +rm -rf $hotspotlog + +if [ $(($atleast)) -ge $(($numoffiles-1)) ]; then + echo $msgsuccess +else + echo $msgfail + exit -1 +fi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/7158988/TestFieldMonitor.sh Tue May 07 17:14:42 2013 -0700 @@ -0,0 +1,75 @@ +#!/bin/sh + +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 | Linux | Darwin) + NULL=/dev/null + PS=":" + FS="/" + ;; + Windows_95 | Windows_98 | Windows_ME ) + NULL=NUL + PS=";" + FS="\\" + echo "Test skipped, only for WinNT" + exit 0 + ;; + Windows_NT ) + NULL=NUL + PS=";" + FS="\\" + ;; + CYGWIN_NT* ) + NULL=/dev/null + PS=";" + FS="/" + ;; + CYGWIN_* ) + NULL=/dev/null + PS=";" + FS="/" + echo "Test skipped, only for WinNT" + exit 0 + ;; + * ) + echo "Unrecognized system!" + exit 1; + ;; +esac + +#CLASSPATH=.${PS}${TESTCLASSES} ; export CLASSPATH + +cp ${TESTSRC}${FS}*.java . + +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -fullversion + +${TESTJAVA}${FS}bin${FS}javac -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar *.java + +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar FieldMonitor > test.out + +grep "A fatal error has been detected" test.out > ${NULL} +if [ $? = 0 ]; then + cat test.out + STATUS=1 +fi + +exit $STATUS