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