JOL Hotspot SA Support and Compressed References Implementation
Serkan ÖZAL
serkanozal86 at hotmail.com
Tue Jan 6 11:15:10 UTC 2015
Hi Volker,
Thats right. There is a specific workaround for Debin/Ubuntu. Maybe
there are more for other UNIX based operating systems.
Therefore, I just advice "sudo" for general solution (At least, it works
for Ubuntu and MacOSX).
But if we can found another solution for this particular problem, it
will be great.
I am willing to listen all ideas.
Regards.
--
Serkan ÖZAL
> 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