JOL Hotspot SA Support and Compressed References Implementation
Volker Simonis
volker.simonis at gmail.com
Mon Jan 5 09:37:24 UTC 2015
On Sun, Jan 4, 2015 at 3:24 PM, Serkan ÖZAL <serkanozal86 at hotmail.com> wrote:
> Hi Aleksey,
>
> I have prepared a patch (sending as attahced to this mail) about for
> embedded Hotspot SA support infrastructure and compressed reference
> implementation on top of it for JOL.
> I implemented Hotspot SA support with no compile-time dependency to
> "sa-jdi.jar" as we talked before. At first, required classes is searched at
> current classpath. If not found, then looks to <JAVA_HOME>.
> If it still couldn't be found, Hotspot SA support is skipped gracefully with
> an information message and goes on before.
>
> There is an interface named "HotspotServiceabilityAgentProcessor" for
> executing any business logic on Hotspot SA process and all required
> instances such as "sun.jvm.hotspot.HotSpotAgent" and
> "sun.jvm.hotspot.HotSpotAgent" are passed to "process" method of this
> interface typed implementation in a context instance typed
> "HotspotServiceabilityAgentContext". All processors return their result as
> "HotspotServiceabilityAgentResult" typed response. All requests, processors
> and reponses are serialized/deserialized between current process and Hotspot
> SA process via pipeline.
>
> So for possible future cases, I think we can easily use all magics of
> Hotspot SA API and also JOL API users can implement their own Hotspot SA
> processors and runs on our infrastructure via
> "HotspotServiceabilityAgentSupport" class.
>
> Also, I implemented finding compressed references on top of this
> infrastructure and integrated with "VMSupport" class.
>
> IMPORTANT NOTE:
>
> On some UNIX based operating systems and MacOSX operation system, Hotspot
> Serviceability Agent (SA) process attach may fail due to insufficient
> privilege. So, on these operating systems, user (runs the application) must
> be super user and must be already authenticated for example with "sudo"
> command (also with password) to "/etc/sudoers" file.
>
At least on Debian/Ubuntu this is a known problem which can easily be
fixed by doing:
echo 0 > /proc/sys/kernel/yama/ptrace_scope
or set ptrace_scope to 0 in /etc/sysctl.d/10-ptrace.conf
See https://wiki.ubuntu.com/SecurityTeam/Roadmap/KernelHardening#ptrace_Protection
for more details.
Regards,
Volker
> http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7129704
> http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7050524
> http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7112802
> http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7160774
>
>
> I hope it is OK. Waiting for your comments about patch.
>
> Regards.
>
> --
>
> Serkan ÖZAL
>
> diff -r be8776814beb
> jol-core/src/main/java/org/openjdk/jol/util/HotspotServiceabilityAgentSupport.java
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++
> b/jol-core/src/main/java/org/openjdk/jol/util/HotspotServiceabilityAgentSupport.java
> Sun Jan 04 16:03:47 2015 +0200
> @@ -0,0 +1,604 @@
> +/*
> + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights
> reserved.
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
> + *
> + * This code is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 only, as
> + * published by the Free Software Foundation. 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.
> + */
> +package org.openjdk.jol.util;
> +
> +import java.io.ByteArrayOutputStream;
> +import java.io.File;
> +import java.io.IOException;
> +import java.io.ObjectInputStream;
> +import java.io.ObjectOutputStream;
> +import java.io.Serializable;
> +import java.lang.management.ManagementFactory;
> +import java.lang.management.RuntimeMXBean;
> +import java.lang.reflect.Field;
> +import java.lang.reflect.InvocationTargetException;
> +import java.lang.reflect.Method;
> +import java.util.ArrayList;
> +import java.util.List;
> +
> +import org.openjdk.jol.util.sa.HotspotServiceabilityAgentContext;
> +import org.openjdk.jol.util.sa.HotspotServiceabilityAgentProcessor;
> +import org.openjdk.jol.util.sa.HotspotServiceabilityAgentResult;
> +import org.openjdk.jol.util.sa.impl.HotspotServiceabilityAgentUtil;
> +import
> org.openjdk.jol.util.sa.impl.compressedrefs.HotspotSACompressedReferencesProcessor;
> +import
> org.openjdk.jol.util.sa.impl.compressedrefs.HotspotSACompressedReferencesResult;
> +
> +import sun.management.VMManagement;
> +
> +/**
> + * Hotspot Serviceability Agent support.
> + *
> + * IMPORTANT NOTE:
> + * On some UNIX based operating systems and MacOSX operation system,
> + * Hotspot Serviceability Agent (SA) process attach may fail due to
> insufficient privilege.
> + * So, on these operating systems, user (runs the application) must be
> super user and must be already authenticated
> + * for example with <code>"sudo"</code> command (also with password)
> to <code>"/etc/sudoers"</code> file.
> + *
> + * For more information about <code>"sudo"</code>, please have a look:
> + * @link http://en.wikipedia.org/wiki/Sudo
> + * @link http://linux.about.com/od/commands/l/blcmdl8_sudo.htm
> + *
> + * @see HotspotServiceabilityAgentProcessor
> + * @see HotspotServiceabilityAgentResult
> + *
> + * @see HotspotSACompressedReferencesProcessor
> + * @see HotspotSACompressedReferencesResult
> + *
> + * @author Serkan Ozal
> + */
> +public class HotspotServiceabilityAgentSupport {
> +
> + private static final String SKIP_HOTSPOT_SA_ATTACH_FLAG =
> "jol.skipHotspotSAAttach";
> +
> + private static final int DEFAULT_TIMEOUT_IN_MSECS = 10000; // 10
> seconds
> + private static final int VM_CHECK_PERIOD_SENSITIVITY_IN_MSECS = 1000;
> // 1 seconds
> +
> + private static final boolean enable;
> + private static final int processId;
> + private static final String classpathForAgent;
> + private static final String errorMessage;
> +
> + static {
> + boolean active = true;
> + int currentProcId = -1;
> + String classpathForAgentProc = null;
> + String errorMsg = null;
> +
> + if (Boolean.getBoolean(SKIP_HOTSPOT_SA_ATTACH_FLAG)) {
> + active = false;
> + errorMsg = "Hotspot SA attach skip flag (" +
> SKIP_HOTSPOT_SA_ATTACH_FLAG + ") is set. " +
> + "So skipping Hotspot SA support ...";
> + } else {
> +
> + final String jvmName =
> System.getProperty("java.vm.name").toLowerCase();
> + // Hotspot Serviceability Agent is only supported on Hotspot
> JVM
> + if (!jvmName.contains("hotspot") &&
> !jvmName.contains("openjdk")) {
> + active = false;
> + errorMsg = "Hotspot Serviceabiliy Agent is only
> supported on Hotspot JVM. " +
> + "So skipping Hotspot SA support ...";
> + } else {
> + try {
> + // Find current process id to connect via
> Hotspot agent
> + RuntimeMXBean mxbean =
> ManagementFactory.getRuntimeMXBean();
> + Field jvmField =
> mxbean.getClass().getDeclaredField("jvm");
> + jvmField.setAccessible(true);
> +
> + VMManagement management = (VMManagement)
> jvmField.get(mxbean);
> + Method method =
> management.getClass().getDeclaredMethod("getProcessId");
> + method.setAccessible(true);
> + currentProcId = (Integer) method.invoke(management);
> + } catch (Throwable t) {
> + active = false;
> + errorMsg = "Couldn't find id of current JVM process. "
> +
> + "So skipping Hotspot SA support ...";
> + }
> + }
> +
> + final String currentClasspath =
> normalizePath(ManagementFactory.getRuntimeMXBean().getClassPath());
> + try {
> + // Search it at classpath
> +
> Class.forName(HotspotServiceabilityAgentUtil.HOTSPOT_AGENT_CLASSNAME);
> +
> + // Use current classpath for agent process
> + classpathForAgentProc = currentClasspath;
> + } catch (ClassNotFoundException e1) {
> + try {
> + // If it couldn't be found at classpath, try to
> find it at
> + File hotspotAgentLib =
> + new
> File(normalizePath(System.getProperty("java.home")) + "/../lib/sa-jdi.jar");
> + if (hotspotAgentLib.exists()) {
> + classpathForAgentProc =
> + currentClasspath +
> File.pathSeparator +
> +
> normalizePath(hotspotAgentLib.getAbsolutePath());
> + } else {
> + active = false;
> + errorMsg = "Couldn't find Hotspot SA library
> (sa-jdi.jar) in both classpath and <JAVA_HOME>/../lib/ directory. " +
> + "So skipping Hotspot SA support ...";
> + }
> + } catch (Throwable t2) {
> + active = false;
> + errorMsg = "Couldn't find Hotspot SA library
> (sa-jdi.jar) in both classpath and <JAVA_HOME>/../lib/ directory. " +
> + "So skipping Hotspot SA support ...";
> + }
> + }
> + }
> +
> + enable = active;
> + processId = currentProcId;
> + classpathForAgent = classpathForAgentProc;
> + errorMessage = errorMsg;
> + }
> +
> + private HotspotServiceabilityAgentSupport() {
> +
> + }
> +
> + private static String normalizePath(String path) {
> + return path.replace('\\', '/');
> + }
> +
> + private static void checkEnable() {
> + if (!enable) {
> + throw new IllegalStateException(errorMessage);
> + }
> + }
> +
> + /**
> + * Checks and gets the condition about if "sudo" command is required
> + * for creating external Java process to connect current process as
> Hotspot agent.
> + * On some UNIX based and MacOSX based operations systems,
> + * Hotspot Serviceability Agent (SA) process attach fails due to
> insufficient privilege.
> + * So these processes must be execute as super user.
> + *
> + * See also JVM Bug reports:
> + * @link
> http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7129704
> + * @link
> http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7050524
> + * @link
> http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7112802
> + * @link
> http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7160774
> + * @link https://bugs.openjdk.java.net/browse/JDK-7129704
> + * @link https://bugs.openjdk.java.net/browse/JDK-7050524
> + * @link https://bugs.openjdk.java.net/browse/JDK-7112802
> + * @link https://bugs.openjdk.java.net/browse/JDK-7160774
> + *
> + * @return <code>true</code> if "sudo" command is required,
> otherwise <code>false</code>
> + */
> + private static boolean isSudoRequired() {
> + String osName = System.getProperty("os.name").toLowerCase();
> + if (osName.indexOf("nix") >= 0 || osName.indexOf("nux") >= 0 ||
> osName.indexOf("aix") > 0) { // UNIX based operation system
> + return true;
> + } else if (osName.indexOf("mac") >= 0) { // MacOSX based operation
> system
> + return true;
> + } else {
> + return false;
> + }
> + }
> +
> + private static <R extends HotspotServiceabilityAgentResult, P extends
> HotspotServiceabilityAgentProcessor<R>>
> + R executeOnHotspotSAInternal(P processor, int
> timeoutInMsecs) {
> + checkEnable();
> +
> + // Generate required arguments to create an external Java
> process
> + List<String> args = new ArrayList<String>();
> + if (isSudoRequired()) {
> + args.add("sudo");
> + }
> + args.add(normalizePath(System.getProperty("java.home")) + "/" +
> "bin" + "/" + "java");
> + args.add("-cp");
> + args.add(classpathForAgent);
> + args.add(HotspotServiceabilityAgentSupport.class.getName());
> + args.add(String.valueOf(processId));
> +
> + Process agentProcess = null;
> + try {
> + // Create an external Java process to connect this process as
> Hotspot agent
> + agentProcess = new ProcessBuilder(args).start();
> +
> + HotspotServiceabilityAgentRequest<P> request =
> + new HotspotServiceabilityAgentRequest<P>(processId,
> processor, timeoutInMsecs);
> + AgentConnectionHandlerThread<R, P> agentConnectionHandlerThread
> =
> + new AgentConnectionHandlerThread<R, P>(agentProcess,
> request);
> +
> + // Start handler thread to manage pipeline between current
> process and Hotspot agent process
> + agentConnectionHandlerThread.start();
> +
> + // Wait as timeout duration at most
> + agentConnectionHandlerThread.join(timeoutInMsecs);
> +
> + // Check about if there is a timeout
> + if (!agentConnectionHandlerThread.isFinished()) {
> + agentConnectionHandlerThread.destroy();
> + throw new RuntimeException("Timeout " + "(" +
> timeoutInMsecs + " milliseconds" + ")" +
> + " reached for processor " +
> processor);
> + }
> +
> + // Get response from Hotspot agent process
> + HotspotServiceabilityAgentResponse<R> response =
> agentConnectionHandlerThread.getResponse();
> + if (response.getError() != null) {
> + Throwable error = response.getError();
> + throw new RuntimeException(error.getMessage(), error);
> + }
> + R result = response.getResult();
> +
> + return result;
> + } catch (Throwable t) {
> + throw new RuntimeException(t.getMessage(), t);
> + } finally {
> + if (agentProcess != null) {
> + agentProcess.destroy();
> + }
> + }
> + }
> +
> + private static <P extends HotspotServiceabilityAgentProcessor<?>> P
> createInstance(Class<P> processorClass) {
> + try {
> + return processorClass.newInstance();
> + } catch (Throwable t) {
> + throw new IllegalArgumentException("Could not create instance
> of " + processorClass.getName(), t);
> + }
> + }
> +
> + /**
> + * Manages pipeline (I/O) between current process and Hotspot agent
> process.
> + *
> + * @param <R> the type of {@link HotspotServiceabilityAgentResult}
> + * @param <P> the type of {@link HotspotServiceabilityAgentProcessor}
> + */
> + private static class AgentConnectionHandlerThread<R extends
> HotspotServiceabilityAgentResult, P extends
> HotspotServiceabilityAgentProcessor<R>>
> + extends Thread {
> +
> + private Process agentProcess;
> + private HotspotServiceabilityAgentRequest<P> request;
> + private HotspotServiceabilityAgentResponse<R> response;
> + private ObjectInputStream in;
> + private ObjectOutputStream out;
> + private volatile boolean finished;
> +
> + private AgentConnectionHandlerThread(Process agentProcess,
> HotspotServiceabilityAgentRequest<P> request) {
> + this.agentProcess = agentProcess;
> + this.request = request;
> + }
> +
> + @SuppressWarnings("unchecked")
> + @Override
> + public void run() {
> + try {
> + // Send request Hotspot agent process to execute
> + out = new
> ObjectOutputStream(agentProcess.getOutputStream());
> + out.writeObject(request);
> + out.flush();
> +
> + // Get response from Hotspot agent process
> + in = new
> ObjectInputStream(agentProcess.getInputStream());
> + response = (HotspotServiceabilityAgentResponse<R>)
> in.readObject();
> +
> + finished = true;
> + } catch (Throwable t) {
> + finished = true;
> +
> + throw new RuntimeException(t.getMessage(), t);
> + }
> + }
> +
> + @SuppressWarnings("deprecation")
> + @Override
> + public void destroy() {
> + if (in != null) {
> + try {
> + in.close();
> + } catch (IOException e) {
> + // There is nothing to do, so just ignore
> + }
> + }
> + if (out != null) {
> + try {
> + out.flush();
> + out.close();
> + } catch (IOException e) {
> + // There is nothing to do, so just ignore
> + }
> + }
> + super.destroy();
> + }
> +
> + public HotspotServiceabilityAgentResponse<R> getResponse() {
> + return response;
> + }
> +
> + public boolean isFinished() {
> + return finished;
> + }
> +
> + }
> +
> + /**
> + * Represents request to Hotspot agent process by holding process
> id, timeout and
> + * {@link HotspotServiceabilityAgentProcessor} to execute.
> + *
> + * @param <P> the type of {@link
> HotspotServiceabilityAgentProcessor}
> + */
> + @SuppressWarnings("serial")
> + private static class HotspotServiceabilityAgentRequest<P extends
> HotspotServiceabilityAgentProcessor<?>>
> + implements Serializable {
> +
> + private int processId;
> + private P processor;
> + private int timeout = DEFAULT_TIMEOUT_IN_MSECS;
> +
> + private HotspotServiceabilityAgentRequest() {
> +
> + }
> +
> + private HotspotServiceabilityAgentRequest(int processId, P
> processor) {
> + this.processId = processId;
> + this.processor = processor;
> + }
> +
> + private HotspotServiceabilityAgentRequest(int processId, P
> processor, int timeout) {
> + this.processId = processId;
> + this.processor = processor;
> + this.timeout = timeout;
> + }
> +
> + public int getProcessId() {
> + return processId;
> + }
> +
> + public P getProcessor() {
> + return processor;
> + }
> +
> + public int getTimeout() {
> + return timeout;
> + }
> +
> + }
> +
> + /**
> + * Represents response from Hotspot agent process by holding {@link
> HotspotServiceabilityAgentResult} and
> + * error if occurred.
> + *
> + * @param <R> the type of {@link HotspotServiceabilityAgentResult}
> + */
> + @SuppressWarnings("serial")
> + private static class HotspotServiceabilityAgentResponse<R extends
> HotspotServiceabilityAgentResult>
> + implements Serializable {
> +
> + private R result;
> + private Throwable error;
> +
> + private HotspotServiceabilityAgentResponse() {
> +
> + }
> +
> + private HotspotServiceabilityAgentResponse(R result) {
> + this.result = result;
> + }
> +
> + private HotspotServiceabilityAgentResponse(Throwable error) {
> + this.error = error;
> + }
> +
> + public R getResult() {
> + return result;
> + }
> +
> + public void setResult(R result) {
> + this.result = result;
> + }
> +
> + public Throwable getError() {
> + return error;
> + }
> +
> + public void setError(Throwable error) {
> + this.error = error;
> + }
> +
> + }
> +
> + @SuppressWarnings({ "unchecked", "rawtypes" })
> + public static <R extends HotspotServiceabilityAgentResult, P extends
> HotspotServiceabilityAgentProcessor<R>> void main(final String[] args) {
> + final HotspotServiceabilityAgentResponse<R> response = new
> HotspotServiceabilityAgentResponse();
> + ByteArrayOutputStream bos = new ByteArrayOutputStream();
> + ObjectInputStream in = null;
> + ObjectOutputStream out = null;
> + Object hotspotAgent = null;
> + Method detachMethod = null;
> +
> + try {
> + // Gets request from caller process over standard input
> + in = new ObjectInputStream(System.in);
> + out = new ObjectOutputStream(bos);
> +
> + System.setProperty("sun.jvm.hotspot.debugger.useProcDebugger",
> "true");
> +
> System.setProperty("sun.jvm.hotspot.debugger.useWindbgDebugger", "true");
> +
> + final HotspotServiceabilityAgentRequest<P> request =
> (HotspotServiceabilityAgentRequest<P>) in.readObject();
> +
> + final Class<?> hotspotAgentClass =
> HotspotServiceabilityAgentUtil.getHotspotAgentClass();
> + hotspotAgent =
> HotspotServiceabilityAgentUtil.createHotspotAgentInstance();
> + final Method attachMethod =
> hotspotAgentClass.getMethod("attach", int.class);
> + detachMethod = hotspotAgentClass.getMethod("detach");
> +
> + Object vm = null;
> +
> + final Object agent = hotspotAgent;
> + Thread t = new Thread() {
> + public void run() {
> + try {
> + // Attach to the caller process as Hotspot agent
> + attachMethod.invoke(agent, request.getProcessId());
> + } catch (IllegalArgumentException e) {
> + throw new RuntimeException("Cannot attach to
> process as Hotspot SA", e);
> + } catch (IllegalAccessException e) {
> + throw new RuntimeException("Cannot attach to
> process as Hotspot SA", e);
> + } catch (InvocationTargetException e) {
> + throw new RuntimeException("Cannot attach to
> process as Hotspot SA", e);
> + }
> + };
> + };
> + t.start();
> +
> + // Check until timeout
> + for (int i = 0; i < request.getTimeout(); i +=
> VM_CHECK_PERIOD_SENSITIVITY_IN_MSECS) {
> + Thread.sleep(VM_CHECK_PERIOD_SENSITIVITY_IN_MSECS); // Wait
> a little before an attempt
> + try {
> + if ((vm =
> HotspotServiceabilityAgentUtil.getVMInstance()) != null) {
> + break;
> + }
> + } catch (Throwable err) {
> + // There is nothing to do, try another
> + }
> + }
> +
> + // Check about if VM is initialized and ready to use
> + if (vm != null) {
> + final P processor = request.getProcessor();
> + // Execute processor and gets its result
> + final R result = processor.process(new
> HotspotServiceabilityAgentContext(hotspotAgent, vm));
> + response.setResult(result);
> + } else {
> + throw new IllegalStateException("VM couldn't be initialized
> !");
> + }
> + } catch (Throwable t) {
> + // If there is an error, attach it to response
> + response.setError(t);
> + } finally {
> + if (out != null) {
> + try {
> + // Send response back to caller process over standard
> output
> + out.writeObject(response);
> + out.flush();
> + System.out.write(bos.toByteArray());
> + } catch (IOException e) {
> + // There is nothing to do, so just ignore
> + }
> + }
> + if (hotspotAgent != null && detachMethod != null) {
> + try {
> + detachMethod.invoke(hotspotAgent);
> + } catch (IllegalArgumentException e) {
> + // There is nothing to do, so just ignore
> + } catch (IllegalAccessException e) {
> + // There is nothing to do, so just ignore
> + } catch (InvocationTargetException e) {
> + // There is nothing to do, so just ignore
> + }
> + }
> + }
> + }
> +
> + /**
> + * Returns <code>true</code> if Hotspot Serviceability Agent support
> is enable, otherwise <code>false</code>.
> + *
> + * @return the enable state of Hotspot Serviceability Agent support
> + */
> + public static boolean isEnable() {
> + return enable;
> + }
> +
> + /**
> + * Executes given typed {@link HotspotServiceabilityAgentProcessor} on
> Hotspot agent process and returns
> + * {@link HotspotServiceabilityAgentResult} as result.
> + *
> + * @param <R> the type of {@link HotspotServiceabilityAgentResult}
> + * @param <P> the type of {@link HotspotServiceabilityAgentProcessor}
> + * @param processorClass the type of {@link
> HotspotServiceabilityAgentProcessor} instance to execute
> + * @return the {@link HotspotServiceabilityAgentProcessor} instance as
> result of processor execution
> + */
> + public static <R extends HotspotServiceabilityAgentResult, P extends
> HotspotServiceabilityAgentProcessor<R>>
> + R executeOnHotspotSA(Class<P> processorClass) {
> + return executeOnHotspotSA(createInstance(processorClass),
> DEFAULT_TIMEOUT_IN_MSECS);
> + }
> +
> + /**
> + * Executes given {@link HotspotServiceabilityAgentProcessor} on
> Hotspot agent process and returns
> + * {@link HotspotServiceabilityAgentResult} instance as result.
> + *
> + * @param <R> the type of {@link HotspotServiceabilityAgentResult}
> + * @param <P> the type of {@link HotspotServiceabilityAgentProcessor}
> + * @param processor the {@link HotspotServiceabilityAgentProcessor}
> instance to execute
> + * @return the {@link HotspotServiceabilityAgentProcessor} instance as
> result of processor execution
> + */
> + public static <R extends HotspotServiceabilityAgentResult, P extends
> HotspotServiceabilityAgentProcessor<R>>
> + R executeOnHotspotSA(P processor) {
> + return executeOnHotspotSAInternal(processor,
> DEFAULT_TIMEOUT_IN_MSECS);
> + }
> +
> + /**
> + * Executes given typed {@link HotspotServiceabilityAgentProcessor} on
> Hotspot agent process and returns
> + * {@link HotspotServiceabilityAgentResult} as result.
> + *
> + * @param <R> the type of {@link HotspotServiceabilityAgentResult}
> + * @param <P> the type of {@link HotspotServiceabilityAgentProcessor}
> + * @param processorClass the type of {@link
> HotspotServiceabilityAgentProcessor} instance to execute
> + * @param timeoutInMsecs the timeout in milliseconds to wait at most
> for terminating connection
> + * between current process and Hotspot agent
> process.
> + * @return the {@link HotspotServiceabilityAgentProcessor} instance as
> result of processor execution
> + */
> + public static <R extends HotspotServiceabilityAgentResult, P extends
> HotspotServiceabilityAgentProcessor<R>>
> + R executeOnHotspotSA(Class<P> processorClass, int
> timeoutInMsecs) {
> + return executeOnHotspotSA(createInstance(processorClass),
> timeoutInMsecs);
> + }
> +
> + /**
> + * Executes given {@link HotspotServiceabilityAgentProcessor} on
> Hotspot agent process and returns
> + * {@link HotspotServiceabilityAgentResult} instance as result.
> + *
> + * @param <R> the type of {@link HotspotServiceabilityAgentResult}
> + * @param <P> the type of {@link HotspotServiceabilityAgentProcessor}
> + * @param processor the {@link HotspotServiceabilityAgentProcessor}
> instance to execute
> + * @param timeoutInMsecs the timeout in milliseconds to wait at most
> for terminating connection
> + * between current process and Hotspot agent
> process.
> + * @return the {@link HotspotServiceabilityAgentProcessor} instance as
> result of processor execution
> + */
> + public static <R extends HotspotServiceabilityAgentResult, P extends
> HotspotServiceabilityAgentProcessor<R>>
> + R executeOnHotspotSA(P processor, int timeoutInMsecs) {
> + return executeOnHotspotSAInternal(processor, timeoutInMsecs);
> + }
> +
> + /**
> + * Gets the compressed references information as {@link
> HotspotSACompressedReferencesResult} instance.
> + *
> + * @return the compressed references information as {@link
> HotspotSACompressedReferencesResult} instance
> + */
> + public static HotspotSACompressedReferencesResult
> getCompressedReferences() {
> + return
> executeOnHotspotSA(HotspotSACompressedReferencesProcessor.class);
> + }
> +
> + /**
> + * Gives details about Hotspot Serviceability Agent support.
> + *
> + * @return the string representation of Hotspot Serviceability Agent
> support
> + */
> + public static String details() {
> + return "HotspotServiceabilityAgentSupport [" +
> + "enable=" + enable + ", " +
> + "processId=" + processId + ", " +
> + "classpathForAgent=" + classpathForAgent + ", " +
> + "errorMessage=" + errorMessage + "]";
> + }
> +
> +}
> diff -r be8776814beb
> jol-core/src/main/java/org/openjdk/jol/util/VMSupport.java
> --- a/jol-core/src/main/java/org/openjdk/jol/util/VMSupport.java Fri
> Dec 19 01:45:21 2014 +0300
> +++ b/jol-core/src/main/java/org/openjdk/jol/util/VMSupport.java Sun
> Jan 04 16:03:47 2015 +0200
> @@ -27,12 +27,15 @@
> import org.openjdk.jol.info.ClassData;
> import org.openjdk.jol.info.ClassLayout;
> import org.openjdk.jol.layouters.CurrentLayouter;
> +import
> org.openjdk.jol.util.sa.impl.compressedrefs.HotspotSACompressedReferencesResult;
> +
> import sun.misc.Unsafe;
>
> import javax.management.MBeanServer;
> import javax.management.ObjectName;
> import javax.management.RuntimeMBeanException;
> import javax.management.openmbean.CompositeDataSupport;
> +
> import java.io.PrintWriter;
> import java.io.StringWriter;
> import java.lang.management.ManagementFactory;
> @@ -56,12 +59,24 @@
>
> public static final String VM_NAME;
> public static final int ADDRESS_SIZE;
> + public static final int REF_SIZE;
> public static final int OBJ_ALIGNMENT;
> public static final int OBJ_HEADER_SIZE;
> +
> public static final boolean USE_COMPRESSED_REFS;
> + public static final long COMPRESSED_REF_BASE;
> public static final int COMPRESSED_REF_SHIFT;
> -
> - public static final int REF_SIZE;
> +
> + public static final int OOP_SIZE;
> + public static final boolean USE_COMPRESSED_OOP;
> + public static final long COMPRESSED_OOP_BASE;
> + public static final int COMPRESSED_OOP_SHIFT;
> +
> + public static final int KLASS_PTR_SIZE;
> + public static final boolean USE_COMPRESSED_KLASS;
> + public static final long COMPRESSED_KLASS_BASE;
> + public static final int COMPRESSED_KLASS_SHIFT;
> +
> public static final int BOOLEAN_SIZE;
> public static final int BYTE_SIZE;
> public static final int CHAR_SIZE;
> @@ -107,16 +122,32 @@
> headerSize = -1;
> }
>
> + ADDRESS_SIZE = U.addressSize();
> +
> VMOptions opts = VMOptions.getOptions();
>
> - ADDRESS_SIZE = U.addressSize();
> + VM_NAME = opts.name;
> + REF_SIZE = opts.sizeReference;
> + OBJ_ALIGNMENT = opts.objectAlignment;
> OBJ_HEADER_SIZE = headerSize;
> +
> + // For backward compatibility, OOP compressed reference mode can be
> used as default compressed reference mode
> + USE_COMPRESSED_REFS = opts.compressedOopRef;
> + // For backward compatibility, OOP compressed base address can be
> used as default compressed reference base address
> + COMPRESSED_REF_BASE = opts.compressedOopBase;
> + // For backward compatibility, OOP compressed shift size can be
> used as default compressed reference shift size
> + COMPRESSED_REF_SHIFT = opts.compressedOopShift;
> +
> + OOP_SIZE = opts.oopSize;
> + USE_COMPRESSED_OOP = opts.compressedOopRef;
> + COMPRESSED_OOP_BASE = opts.compressedOopBase;
> + COMPRESSED_OOP_SHIFT = opts.compressedOopShift;
> +
> + KLASS_PTR_SIZE = opts.klassPtrSize;
> + USE_COMPRESSED_KLASS = opts.compressedKlassRef;
> + COMPRESSED_KLASS_BASE = opts.compressedKlassBase;
> + COMPRESSED_KLASS_SHIFT = opts.compressedKlassShift;
>
> - VM_NAME = opts.name;
> - USE_COMPRESSED_REFS = opts.compressedRef;
> - COMPRESSED_REF_SHIFT = opts.compressRefShift;
> - OBJ_ALIGNMENT = opts.objectAlignment;
> - REF_SIZE = opts.sizeReference;
> BOOLEAN_SIZE = opts.sizeBoolean;
> BYTE_SIZE = opts.sizeByte;
> CHAR_SIZE = opts.sizeChar;
> @@ -129,7 +160,47 @@
>
> public static long toNativeAddress(long address) {
> if (USE_COMPRESSED_REFS) {
> - return address << COMPRESSED_REF_SHIFT;
> + return COMPRESSED_REF_BASE + (address << COMPRESSED_REF_SHIFT);
> + } else {
> + return address;
> + }
> + }
> +
> + public static long toJvmAddress(long address) {
> + if (USE_COMPRESSED_REFS) {
> + return (address >> COMPRESSED_REF_SHIFT) - COMPRESSED_REF_BASE;
> + } else {
> + return address;
> + }
> + }
> +
> + public static long toNativeOopAddress(long address) {
> + if (USE_COMPRESSED_OOP) {
> + return COMPRESSED_OOP_BASE + (address << COMPRESSED_OOP_SHIFT);
> + } else {
> + return address;
> + }
> + }
> +
> + public static long toJvmOopAddress(long address) {
> + if (USE_COMPRESSED_OOP) {
> + return (address >> COMPRESSED_OOP_SHIFT) - COMPRESSED_OOP_BASE;
> + } else {
> + return address;
> + }
> + }
> +
> + public static long toNativeKlassAddress(long address) {
> + if (USE_COMPRESSED_KLASS) {
> + return COMPRESSED_KLASS_BASE + (address <<
> COMPRESSED_KLASS_SHIFT);
> + } else {
> + return address;
> + }
> + }
> +
> + public static long toJvmKlassAddress(long address) {
> + if (USE_COMPRESSED_KLASS) {
> + return (address >> COMPRESSED_KLASS_SHIFT) -
> COMPRESSED_KLASS_BASE;
> } else {
> return address;
> }
> @@ -144,8 +215,39 @@
> PrintWriter out = new PrintWriter(sw);
>
> out.println("Running " + (ADDRESS_SIZE * 8) + "-bit " + VM_NAME + "
> VM.");
> - if (USE_COMPRESSED_REFS)
> - out.println("Using compressed references with " +
> COMPRESSED_REF_SHIFT + "-bit shift.");
> +
> + String javaSpecVersion =
> System.getProperty("java.specification.version");
> + // Since Java 8 (Java 8 and Java 9) has different compressed
> reference configuration for OOP and Klass
> + if (javaSpecVersion.equals("1.8") || javaSpecVersion.equals("1.9"))
> {
> + if (USE_COMPRESSED_OOP) {
> + if (COMPRESSED_OOP_BASE != 0) {
> + out.println("Using compressed oop with " +
> +
> formatAddressAsHexByAddressSize(COMPRESSED_OOP_BASE) + " base address and "
> +
> + COMPRESSED_OOP_SHIFT + "-bit shift.");
> + } else {
> + out.println("Using compressed oop with " +
> COMPRESSED_OOP_SHIFT + "-bit shift.");
> + }
> + }
> + if (USE_COMPRESSED_KLASS) {
> + if (COMPRESSED_KLASS_BASE != 0) {
> + out.println("Using compressed klass with " +
> +
> formatAddressAsHexByAddressSize(COMPRESSED_KLASS_BASE) + " base address and
> " +
> + COMPRESSED_KLASS_SHIFT + "-bit shift.");
> + } else {
> + out.println("Using compressed klass with " +
> COMPRESSED_KLASS_SHIFT + "-bit shift.");
> + }
> + }
> + } else {
> + if (USE_COMPRESSED_REFS) {
> + if (COMPRESSED_REF_BASE != 0) {
> + out.println("Using compressed references with " +
> +
> formatAddressAsHexByAddressSize(COMPRESSED_REF_BASE) + " base address and "
> +
> + COMPRESSED_REF_SHIFT + "-bit shift.");
> + } else {
> + out.println("Using compressed references with " +
> COMPRESSED_REF_SHIFT + "-bit shift.");
> + }
> + }
> + }
> out.println("Objects are " + OBJ_ALIGNMENT + " bytes aligned.");
>
> out.printf("%-19s: %d, %d, %d, %d, %d, %d, %d, %d, %d [bytes]%n",
> @@ -177,6 +279,11 @@
> out.close();
> return sw.toString();
> }
> +
> + private static String formatAddressAsHexByAddressSize(long address) {
> + return "0x" + String.format("%" + (ADDRESS_SIZE * 2) + "s",
> +
> Long.toHexString(COMPRESSED_KLASS_BASE).toUpperCase()).replace(' ', '0');
> + }
>
> private static Object instantiateType(int type) {
> switch (type) {
> @@ -261,10 +368,16 @@
>
> private static class VMOptions {
> private final String name;
> - private final boolean compressedRef;
> - private final int compressRefShift;
> private final int objectAlignment;
> -
> + private final int oopSize;
> + private final boolean compressedOopRef;
> + private final long compressedOopBase;
> + private final int compressedOopShift;
> + private final int klassPtrSize;
> + private final boolean compressedKlassRef;
> + private final long compressedKlassBase;
> + private final int compressedKlassShift;
> +
> private final int sizeReference;
> private final int sizeBoolean = getMinDiff(MyBooleans4.class);
> private final int sizeByte = getMinDiff(MyBytes4.class);
> @@ -291,26 +404,60 @@
> this.name = name;
> this.sizeReference = U.addressSize();
> this.objectAlignment = guessAlignment(this.sizeReference);
> - this.compressedRef = false;
> - this.compressRefShift = 1;
> + this.oopSize = sizeReference;
> + this.compressedOopRef = false;
> + this.compressedOopBase = 0L;
> + this.compressedOopShift = 0;
> + this.klassPtrSize = sizeReference;
> + this.compressedKlassRef = false;
> + this.compressedKlassBase = 0L;
> + this.compressedKlassShift = 0;
> }
>
> public VMOptions(String name, int align) {
> this.name = name;
> this.sizeReference = 4;
> this.objectAlignment = align;
> - this.compressedRef = true;
> - this.compressRefShift = MathUtil.log2p(align);
> + this.oopSize = sizeReference;
> + this.compressedOopRef = true;
> + this.compressedOopBase = 0L;
> + this.compressedOopShift = MathUtil.log2p(align);
> + this.klassPtrSize = sizeReference;
> + this.compressedKlassRef = true;
> + this.compressedKlassBase = 0L;
> + this.compressedKlassShift = MathUtil.log2p(align);
> }
>
> public VMOptions(String name, int align, int compRefShift) {
> this.name = name;
> this.sizeReference = 4;
> this.objectAlignment = align;
> - this.compressedRef = true;
> - this.compressRefShift = compRefShift;
> + this.oopSize = sizeReference;
> + this.compressedOopRef = true;
> + this.compressedOopBase = 0L;
> + this.compressedOopShift = compRefShift;
> + this.klassPtrSize = sizeReference;
> + this.compressedKlassRef = true;
> + this.compressedKlassBase = 0L;
> + this.compressedKlassShift = compRefShift;
> }
> -
> +
> + public VMOptions(String name, int align, int oopSize, boolean
> compOopRef, long compOopBase, int compOopShift,
> + int klassPtrSize, boolean compKlassRef, long compKlassBase,
> int compKlassShift) {
> + this.name = name;
> + // Use OOP size as reference size
> + this.sizeReference = oopSize;
> + this.objectAlignment = align;
> + this.oopSize = oopSize;
> + this.compressedOopRef = compOopRef;
> + this.compressedOopBase = compOopBase;
> + this.compressedOopShift = compOopShift;
> + this.klassPtrSize = klassPtrSize;
> + this.compressedKlassRef = compKlassRef;
> + this.compressedKlassBase = compKlassBase;
> + this.compressedKlassShift = compKlassShift;
> + }
> +
> private static VMOptions getOptions() {
> // try Hotspot
> VMOptions hsOpts = getHotspotSpecifics();
> @@ -346,6 +493,29 @@
> }
>
> try {
> + try {
> + HotspotSACompressedReferencesResult
> compressedReferencesInfo =
> +
> HotspotServiceabilityAgentSupport.getCompressedReferences();
> + if (compressedReferencesInfo != null) {
> + return new VMOptions("HotSpot",
> +
> compressedReferencesInfo.getObjectAlignment(),
> +
> compressedReferencesInfo.getOopSize(),
> +
> compressedReferencesInfo.isCompressedOopsEnabled(),
> +
> compressedReferencesInfo.getNarrowOopBase(),
> +
> compressedReferencesInfo.getNarrowOopShift(),
> +
> compressedReferencesInfo.getKlassPtrSize(),
> +
> compressedReferencesInfo.isCompressedKlassPointersEnabled(),
> +
> compressedReferencesInfo.getNarrowKlassBase(),
> +
> compressedReferencesInfo.getNarrowKlassShift());
> + } else {
> + System.out.println("Compressed references
> information couldn't be found via Hotspot SA.");
> + System.out.println("So skipping Hotspot SA support
> to find compressed references ...");
> + }
> + } catch (Throwable t) {
> + System.err.println(t.getMessage());
> + System.out.println("So skipping Hotspot SA support to
> find compressed references ...");
> + }
> +
> MBeanServer server =
> ManagementFactory.getPlatformMBeanServer();
>
> try {
> diff -r be8776814beb
> jol-core/src/main/java/org/openjdk/jol/util/sa/HotspotServiceabilityAgentContext.java
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++
> b/jol-core/src/main/java/org/openjdk/jol/util/sa/HotspotServiceabilityAgentContext.java
> Sun Jan 04 16:03:47 2015 +0200
> @@ -0,0 +1,81 @@
> +/*
> + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights
> reserved.
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
> + *
> + * This code is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 only, as
> + * published by the Free Software Foundation. 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.
> + */
> +package org.openjdk.jol.util.sa;
> +
> +/**
> + * Wrapper class to hold common necessary objects for Hotspot
> Serviceability Agent API Usage.
> + * It is passed to {@link
> HotspotServiceabilityAgentProcessor#process(HotspotServiceabilityAgentContext)}
> method
> + * as parameter and designed for no-change on signature of this method
> + * since other objects may be added to context at the next versions.
> + *
> + * @see sun.jvm.hotspot.HotSpotAgent
> + * @see sun.jvm.hotspot.runtime.VM
> + *
> + * @author Serkan Ozal
> + */
> +public final class HotspotServiceabilityAgentContext {
> +
> + /**
> + * The <code>hotspotAgent<code> property is defined as {@link Object}
> because of no compile time dependency to
> + * {@link sun.jvm.hotspot.HotSpotAgent} class in Hotspot Serviceability
> Agent (sa-jdi.jar).
> + * So the actual type of this property is {@link
> sun.jvm.hotspot.HotSpotAgent}.
> + */
> + private Object hotspotAgent;
> +
> + /**
> + * The <code>vm<code> property is defined as {@link Object} because of
> no compile time dependency to
> + * {@link sun.jvm.hotspot.runtime.VM} class in Hotspot Serviceability
> Agent (sa-jdi.jar).
> + * So the actual type of this property is {@link
> sun.jvm.hotspot.runtime.VM}.
> + */
> + private Object vm;
> +
> + public HotspotServiceabilityAgentContext() {
> +
> + }
> +
> + public HotspotServiceabilityAgentContext(Object hotspotAgent, Object
> vm) {
> + this.hotspotAgent = hotspotAgent;
> + this.vm = vm;
> + }
> +
> + public Object getHotspotAgent() {
> + return hotspotAgent;
> + }
> +
> + public HotspotServiceabilityAgentContext setHotspotAgent(Object
> hotspotAgent) {
> + this.hotspotAgent = hotspotAgent;
> + return this;
> + }
> +
> + public Object getVm() {
> + return vm;
> + }
> +
> + public HotspotServiceabilityAgentContext setVm(Object vm) {
> + this.vm = vm;
> + return this;
> + }
> +
> +}
> diff -r be8776814beb
> jol-core/src/main/java/org/openjdk/jol/util/sa/HotspotServiceabilityAgentProcessor.java
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++
> b/jol-core/src/main/java/org/openjdk/jol/util/sa/HotspotServiceabilityAgentProcessor.java
> Sun Jan 04 16:03:47 2015 +0200
> @@ -0,0 +1,53 @@
> +/*
> + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights
> reserved.
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
> + *
> + * This code is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 only, as
> + * published by the Free Software Foundation. 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.
> + */
> +package org.openjdk.jol.util.sa;
> +
> +import java.io.Serializable;
> +
> +/**
> + * Interface for processors which do some stuff via Hotspot Serviceability
> Agent API on Hotspot internals.
> + *
> + * {@link HotspotServiceabilityAgentProcessor} implementations must be
> fully (including its fields) serializable.
> + * So if there is any field will not be serialized, it must be ignored or
> serialization logic must be customized.
> + * Please see {@link
> http://www.oracle.com/technetwork/articles/java/javaserial-1536170.html} for
> more details.
> + * In addition, since processors is serialized/deserialized, they must have
> default constructor.
> + *
> + * @see HotspotServiceabilityAgentContext
> + * @see HotspotServiceabilityAgentResult
> + *
> + * @author Serkan Ozal
> + */
> +public interface HotspotServiceabilityAgentProcessor<O extends
> HotspotServiceabilityAgentResult> extends Serializable {
> +
> + /**
> + * Takes the {@link HotspotServiceabilityAgentContext} instance and
> processes its
> + * own logic over this instance.
> + *
> + * @param context the {@link HotspotServiceabilityAgentContext}
> instance wraps all necessary objects.
> + * @return the {@link HotspotServiceabilityAgentResult} as result
> + */
> + O process(HotspotServiceabilityAgentContext context);
> +
> +}
> diff -r be8776814beb
> jol-core/src/main/java/org/openjdk/jol/util/sa/HotspotServiceabilityAgentResult.java
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++
> b/jol-core/src/main/java/org/openjdk/jol/util/sa/HotspotServiceabilityAgentResult.java
> Sun Jan 04 16:03:47 2015 +0200
> @@ -0,0 +1,42 @@
> +/*
> + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights
> reserved.
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
> + *
> + * This code is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 only, as
> + * published by the Free Software Foundation. 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.
> + */
> +package org.openjdk.jol.util.sa;
> +
> +import java.io.Serializable;
> +
> +/**
> + * Interface for types of {@link
> HotspotServiceabilityAgentProcessor#process(HotspotServiceabilityAgentContext)}
> return.
> + * It is designed to hold all results under a hierarchy.
> + *
> + * {@link HotspotServiceabilityAgentResult} implementations must be fully
> (including its fields) serializable.
> + * So if there is any field will not be serialized, it must be ignored or
> serialization logic must be customized.
> + * Please see {@link
> http://www.oracle.com/technetwork/articles/java/javaserial-1536170.html} for
> more details.
> + * In addition, since processors is serialized/deserialized, they must have
> default constructor.
> + *
> + * @author Serkan Ozal
> + */
> +public interface HotspotServiceabilityAgentResult extends Serializable {
> +
> +}
> diff -r be8776814beb
> jol-core/src/main/java/org/openjdk/jol/util/sa/impl/HotspotServiceabilityAgentUtil.java
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++
> b/jol-core/src/main/java/org/openjdk/jol/util/sa/impl/HotspotServiceabilityAgentUtil.java
> Sun Jan 04 16:03:47 2015 +0200
> @@ -0,0 +1,75 @@
> +/*
> + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights
> reserved.
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
> + *
> + * This code is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 only, as
> + * published by the Free Software Foundation. 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.
> + */
> +package org.openjdk.jol.util.sa.impl;
> +
> +import java.lang.reflect.InvocationTargetException;
> +import java.lang.reflect.Method;
> +
> +import org.openjdk.jol.util.HotspotServiceabilityAgentSupport;
> +
> +/**
> + * Hotspot Serviceability Agent utility.
> + * It was designed for doing some utility stuff without touching {@link
> HotspotServiceabilityAgentSupport}
> + * class because of its static initializer.
> + *
> + * @author Serkan Ozal
> + */
> +public class HotspotServiceabilityAgentUtil {
> +
> + public static final String HOTSPOT_AGENT_CLASSNAME =
> "sun.jvm.hotspot.HotSpotAgent";
> + public static final String VM_CLASSNAME = "sun.jvm.hotspot.runtime.VM";
> + public static final String UNIVERSE_CLASSNAME =
> "sun.jvm.hotspot.memory.Universe";
> +
> + private HotspotServiceabilityAgentUtil() {
> +
> + }
> +
> + public static Class<?> getHotspotAgentClass() throws
> ClassNotFoundException {
> + return Class.forName(HOTSPOT_AGENT_CLASSNAME);
> + }
> +
> + public static Object createHotspotAgentInstance()
> + throws ClassNotFoundException, InstantiationException,
> IllegalAccessException {
> + Class<?> hotspotAgentClass =
> Class.forName(HOTSPOT_AGENT_CLASSNAME);
> + return hotspotAgentClass.newInstance();
> + }
> +
> + public static Class<?> getVmClass() throws ClassNotFoundException {
> + return Class.forName(VM_CLASSNAME);
> + }
> +
> + public static Object getVMInstance()
> + throws ClassNotFoundException, InstantiationException,
> IllegalAccessException,
> + SecurityException, NoSuchMethodException,
> IllegalArgumentException, InvocationTargetException {
> + Class<?> vmClass = Class.forName(VM_CLASSNAME);
> + Method getVmMethod = vmClass.getMethod("getVM");
> + return getVmMethod.invoke(null);
> + }
> +
> + public static Class<?> getUniverseClass() throws
> ClassNotFoundException {
> + return Class.forName(UNIVERSE_CLASSNAME);
> + }
> +
> +}
> diff -r be8776814beb
> jol-core/src/main/java/org/openjdk/jol/util/sa/impl/compressedrefs/HotspotSACompressedReferencesProcessor.java
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++
> b/jol-core/src/main/java/org/openjdk/jol/util/sa/impl/compressedrefs/HotspotSACompressedReferencesProcessor.java
> Sun Jan 04 16:03:47 2015 +0200
> @@ -0,0 +1,105 @@
> +/*
> + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights
> reserved.
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
> + *
> + * This code is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 only, as
> + * published by the Free Software Foundation. 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.
> + */
> +package org.openjdk.jol.util.sa.impl.compressedrefs;
> +
> +import java.lang.reflect.Method;
> +
> +import org.openjdk.jol.util.sa.HotspotServiceabilityAgentContext;
> +import org.openjdk.jol.util.sa.HotspotServiceabilityAgentProcessor;
> +import org.openjdk.jol.util.sa.impl.HotspotServiceabilityAgentUtil;
> +
> +/**
> + * {@link HotspotServiceabilityAgentProcessor} implementation to find
> compressed reference informations.
> + *
> + * @author Serkan Ozal
> + */
> + at SuppressWarnings("serial")
> +public class HotspotSACompressedReferencesProcessor
> + implements
> HotspotServiceabilityAgentProcessor<HotspotSACompressedReferencesResult> {
> +
> + @Override
> + public HotspotSACompressedReferencesResult
> process(HotspotServiceabilityAgentContext context) {
> + try {
> + Class<?> universeClass =
> HotspotServiceabilityAgentUtil.getUniverseClass();
> + Class<?> vmClass = HotspotServiceabilityAgentUtil.getVmClass();
> + Object vm = HotspotServiceabilityAgentUtil.getVMInstance();
> +
> + Method getOopSizeMethod = vmClass.getMethod("getOopSize");
> + Method getObjectAlignmentInBytesMethod =
> vmClass.getMethod("getObjectAlignmentInBytes");
> +
> + Method getHeapOopSizeMethod =
> vmClass.getMethod("getHeapOopSize");
> + Method isCompressedOopsEnabledMethod =
> vmClass.getMethod("isCompressedOopsEnabled");
> + Method getNarrowOopBaseMethod =
> universeClass.getMethod("getNarrowOopBase");
> + Method getNarrowOopShiftMethod =
> universeClass.getMethod("getNarrowOopShift");
> +
> + Method getKlassPtrSizeMethod = null;
> + Method isCompressedKlassPointersEnabledMethod = null;
> + Method getNarrowKlassBaseMethod = null;
> + Method getNarrowKlassShiftMethod = null;
> +
> + try {
> + getKlassPtrSizeMethod =
> vmClass.getMethod("getKlassPtrSize");
> + isCompressedKlassPointersEnabledMethod =
> vmClass.getMethod("isCompressedKlassPointersEnabled");
> + getNarrowKlassBaseMethod =
> universeClass.getMethod("getNarrowKlassBase");
> + getNarrowKlassShiftMethod =
> universeClass.getMethod("getNarrowKlassShift");
> + } catch (NoSuchMethodException e) {
> + // There is nothing to do, seems target JVM is not Java 8
> + }
> +
> + int addressSize = ((Long)
> getOopSizeMethod.invoke(vm)).intValue();
> + int objectAlignment = (Integer)
> getObjectAlignmentInBytesMethod.invoke(vm);
> +
> + int oopSize = (Integer) getHeapOopSizeMethod.invoke(vm);
> + boolean compressedOopsEnabled = (Boolean)
> isCompressedOopsEnabledMethod.invoke(vm);
> + long narrowOopBase = (Long)
> getNarrowOopBaseMethod.invoke(null);
> + int narrowOopShift = (Integer)
> getNarrowOopShiftMethod.invoke(null);
> +
> + /*
> + * If compressed klass references is not supported (before Java
> 8),
> + * use compressed oop references values instead of them.
> + */
> +
> + int klassPtrSize = getKlassPtrSizeMethod != null ? (Integer
> )getKlassPtrSizeMethod.invoke(vm) : oopSize;
> + boolean compressedKlassPointersEnabled =
> isCompressedKlassPointersEnabledMethod != null
> + ? (Boolean)
> isCompressedKlassPointersEnabledMethod.invoke(vm) : compressedOopsEnabled;
> + long narrowKlassBase = getNarrowKlassBaseMethod != null ?
> (Long) getNarrowKlassBaseMethod.invoke(null) : narrowOopBase;
> + int narrowKlassShift = getNarrowKlassShiftMethod != null ?
> (Integer) getNarrowKlassShiftMethod.invoke(null) : narrowOopShift;
> +
> + return new HotspotSACompressedReferencesResult(addressSize,
> + objectAlignment,
> + oopSize,
> +
> compressedOopsEnabled,
> + narrowOopBase,
> + narrowOopShift,
> + klassPtrSize,
> +
> compressedKlassPointersEnabled,
> + narrowKlassBase,
> +
> narrowKlassShift);
> + } catch (Throwable t) {
> + throw new RuntimeException(t.getMessage(), t);
> + }
> + }
> +
> +}
> diff -r be8776814beb
> jol-core/src/main/java/org/openjdk/jol/util/sa/impl/compressedrefs/HotspotSACompressedReferencesResult.java
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++
> b/jol-core/src/main/java/org/openjdk/jol/util/sa/impl/compressedrefs/HotspotSACompressedReferencesResult.java
> Sun Jan 04 16:03:47 2015 +0200
> @@ -0,0 +1,181 @@
> +/*
> + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights
> reserved.
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
> + *
> + * This code is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 only, as
> + * published by the Free Software Foundation. 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.
> + */
> +package org.openjdk.jol.util.sa.impl.compressedrefs;
> +
> +import org.openjdk.jol.util.sa.HotspotServiceabilityAgentResult;
> +
> +/**
> + * {@link HotspotServiceabilityAgentResult} implementation for representing
> compressed reference informations as result.
> + *
> + * @author Serkan Ozal
> + */
> + at SuppressWarnings("serial")
> +public class HotspotSACompressedReferencesResult implements
> HotspotServiceabilityAgentResult {
> +
> + private int addressSize;
> + private int objectAlignment;
> +
> + private int oopSize;
> + private boolean compressedOopsEnabled;
> + private long narrowOopBase;
> + private int narrowOopShift;
> +
> + private int klassPtrSize;
> + private boolean compressedKlassPointersEnabled;
> + private long narrowKlassBase;
> + private int narrowKlassShift;
> +
> +
> + public HotspotSACompressedReferencesResult() {
> +
> + }
> +
> + public HotspotSACompressedReferencesResult(int addressSize, int
> objectAlignment, int refSize,
> + boolean compressedRefsEnabled, long narrowBase, int
> narrowShift) {
> + this.addressSize = addressSize;
> + this.objectAlignment = objectAlignment;
> + this.oopSize = refSize;
> + this.compressedOopsEnabled = compressedRefsEnabled;
> + this.narrowOopBase = narrowBase;
> + this.narrowOopShift = narrowShift;
> + this.klassPtrSize = refSize;
> + this.compressedKlassPointersEnabled = compressedRefsEnabled;
> + this.narrowKlassBase = narrowBase;
> + this.narrowKlassShift = narrowShift;
> + }
> +
> + public HotspotSACompressedReferencesResult(int addressSize, int
> objectAlignment, int oopSize, boolean compressedOopsEnabled,
> + long narrowOopBase, int narrowOopShift, int klassPtrSize,
> boolean compressedKlassPointersEnabled,
> + long narrowKlassBase, int narrowKlassShift) {
> + this.addressSize = addressSize;
> + this.objectAlignment = objectAlignment;
> + this.oopSize = oopSize;
> + this.compressedOopsEnabled = compressedOopsEnabled;
> + this.narrowOopBase = narrowOopBase;
> + this.narrowOopShift = narrowOopShift;
> + this.klassPtrSize = klassPtrSize;
> + this.compressedKlassPointersEnabled =
> compressedKlassPointersEnabled;
> + this.narrowKlassBase = narrowKlassBase;
> + this.narrowKlassShift = narrowKlassShift;
> + }
> +
> + public int getAddressSize() {
> + return addressSize;
> + }
> +
> + public void setAddressSize(int addressSize) {
> + this.addressSize = addressSize;
> + }
> +
> + public int getObjectAlignment() {
> + return objectAlignment;
> + }
> +
> + public void setObjectAlignment(int objectAlignment) {
> + this.objectAlignment = objectAlignment;
> + }
> +
> + public int getOopSize() {
> + return oopSize;
> + }
> +
> + public void setOopSize(int oopSize) {
> + this.oopSize = oopSize;
> + }
> +
> + public boolean isCompressedOopsEnabled() {
> + return compressedOopsEnabled;
> + }
> +
> + public void setCompressedOopsEnabled(boolean compressedOopsEnabled) {
> + this.compressedOopsEnabled = compressedOopsEnabled;
> + }
> +
> + public long getNarrowOopBase() {
> + return narrowOopBase;
> + }
> +
> + public void setNarrowOopBase(long narrowOopBase) {
> + this.narrowOopBase = narrowOopBase;
> + }
> +
> + public int getNarrowOopShift() {
> + return narrowOopShift;
> + }
> +
> + public void setNarrowOopShift(int narrowOopShift) {
> + this.narrowOopShift = narrowOopShift;
> + }
> +
> + public int getKlassPtrSize() {
> + return klassPtrSize;
> + }
> +
> + public void setKlassPtrSize(int klassPtrSize) {
> + this.klassPtrSize = klassPtrSize;
> + }
> +
> + public boolean isCompressedKlassPointersEnabled() {
> + return compressedKlassPointersEnabled;
> + }
> +
> + public void setCompressedKlassPointersEnabled(boolean
> compressedKlassPointersEnabled) {
> + this.compressedKlassPointersEnabled =
> compressedKlassPointersEnabled;
> + }
> +
> + public long getNarrowKlassBase() {
> + return narrowKlassBase;
> + }
> +
> + public void setNarrowKlassBase(long narrowKlassBase) {
> + this.narrowKlassBase = narrowKlassBase;
> + }
> +
> + public int getNarrowKlassShift() {
> + return narrowKlassShift;
> + }
> +
> + public void setNarrowKlassShift(int narrowKlassShift) {
> + this.narrowKlassShift = narrowKlassShift;
> + }
> +
> + @Override
> + public String toString() {
> + return "HotspotSACompressedOopsResult [" +
> + "addressSize=" + addressSize + ", " +
> + "objectAlignment=" + objectAlignment + ", " +
> + "oopSize=" + oopSize + ", " +
> + "compressedOopsEnabled=" + compressedOopsEnabled + ", "
> +
> + "narrowOopBase=" + "0x" +
> + String.format("%" + (addressSize * 2) + "s",
> Long.toHexString(narrowOopBase).toUpperCase()).replace(' ', '0') + ", " +
> + "narrowOopShift=" + narrowOopShift + ", " +
> + "klassPtrSize=" + klassPtrSize + ", " +
> + "compressedKlassPointersEnabled=" +
> compressedKlassPointersEnabled + ", " +
> + "narrowKlassBase=" + "0x" +
> + String.format("%" + (addressSize * 2) + "s",
> Long.toHexString(narrowKlassBase).toUpperCase()).replace(' ', '0') + ", " +
> + "narrowKlassShift=" + narrowKlassShift + "]";
> + }
> +
> +}
>
> ...
>
> [Message clipped]
More information about the jol-dev
mailing list