JOL object header information
Rafael Winterhalter
rafael.wth at gmail.com
Thu Dec 18 22:59:31 UTC 2014
Brilliant, thanks. That took significantly less time than my glass fish
patch ;)
2014-12-18 23:48 GMT+01:00 Aleksey Shipilev <aleksey.shipilev at oracle.com>:
>
> Thank you, I have refactored this a bit, and committed:
> https://bugs.openjdk.java.net/browse/CODETOOLS-7901220
> http://hg.openjdk.java.net/code-tools/jol/rev/be8776814beb
>
> -Aleksey.
>
> On 12/19/2014 01:04 AM, Rafael Winterhalter wrote:
> > Hi all, sure thing. Find the patch attached. I signed the OCA a year ago
> > when I patched something for glassfish. If this is valid for JOL, great,
> > otherwise ping me.
> >
> > Index: jol-core/src/main/java/org/openjdk/jol/util/VMSupport.java
> > IDEA additional info:
> > Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
> > <+>UTF-8
> > ===================================================================
> > --- jol-core/src/main/java/org/openjdk/jol/util/VMSupport.java
> (revision 31:9a546334aa57fa0e114db159b2a8a5345c249b3e)
> > +++ jol-core/src/main/java/org/openjdk/jol/util/VMSupport.java
> (revision 31+:9a546334aa57+)
> > @@ -35,13 +35,22 @@
> > import javax.management.openmbean.CompositeDataSupport;
> > import java.io.PrintWriter;
> > import java.io.StringWriter;
> > +import java.io.InputStream;
> > +import java.io.File;
> > +import java.io.FileOutputStream;
> > import java.lang.instrument.Instrumentation;
> > import java.lang.management.ManagementFactory;
> > import java.lang.reflect.Field;
> > +import java.net.URL;
> > +import java.net.URLClassLoader;
> > import java.security.AccessController;
> > import java.security.PrivilegedAction;
> > import java.util.Arrays;
> > import java.util.Random;
> > +import java.util.jar.Attributes;
> > +import java.util.jar.JarEntry;
> > +import java.util.jar.JarOutputStream;
> > +import java.util.jar.Manifest;
> > import java.util.regex.Matcher;
> > import java.util.regex.Pattern;
> >
> > @@ -55,6 +64,8 @@
> >
> > private static Instrumentation INSTRUMENTATION;
> >
> > + private static boolean installAttempt;
> > +
> > public static final Unsafe U;
> >
> > public static final String VM_NAME;
> > @@ -253,6 +264,7 @@
> > private final boolean exactSizeAvail;
> >
> > public SizeInfo(Object o, ClassLayout layout) {
> > + VMSupport.installInstrumentation();
> > exactSizeAvail = VMSupport.INSTRUMENTATION != null && o !=
> null;
> > size = exactSizeAvail ? (int)
> VMSupport.INSTRUMENTATION.getObjectSize(o) : layout.instanceSize();
> > }
> > @@ -418,6 +430,7 @@
> > }
> >
> > public static int sizeOf(Object o) {
> > + installInstrumentation();
> > if (VMSupport.INSTRUMENTATION != null) {
> > return VMSupport.align((int)
> VMSupport.INSTRUMENTATION.getObjectSize(o));
> > }
> > @@ -425,6 +438,79 @@
> > return new
> CurrentLayouter().layout(ClassData.parseInstance(o)).instanceSize();
> > }
> >
> > + private static void installInstrumentation() {
> > + if (!installAttempt) {
> > + try {
> > + doInstall();
> > + } catch (Exception ignored) {
> > + }
> > + }
> > + }
> > +
> > + private static synchronized void doInstall() throws Exception {
> > + if (installAttempt) {
> > + return;
> > + }
> > + installAttempt = true;
> > + ClassLoader classLoader = new URLClassLoader(new URL[]{new
> File(System.getProperty("java.home")
> > + .replace('\\', '/') +
> "/../lib/tools.jar").toURI().toURL()}, null);
> > + Class<?> virtualMachine =
> classLoader.loadClass("com.sun.tools.attach.VirtualMachine");
> > + String runtimeName =
> ManagementFactory.getRuntimeMXBean().getName();
> > + Object virtualMachineInstance =
> virtualMachine.getDeclaredMethod("attach", String.class)
> > + .invoke(null, runtimeName.substring(0,
> runtimeName.indexOf('@')));
> > + try {
> > + File agentFile = File.createTempFile("jolAgent", ".jar");
> > + try {
> > + saveAgentJar(agentFile);
> > + virtualMachine.getDeclaredMethod("loadAgent",
> String.class, String.class)
> > + .invoke(virtualMachineInstance,
> agentFile.getAbsolutePath(), "");
> > + INSTRUMENTATION = doGetInstrumentation();
> > + } finally {
> > + agentFile.delete();
> > + }
> > + } finally {
> > +
> virtualMachine.getDeclaredMethod("detach").invoke(virtualMachineInstance);
> > + }
> > + }
> > +
> > + private static Instrumentation doGetInstrumentation() {
> > + try {
> > + Field field = ClassLoader.getSystemClassLoader()
> > + .loadClass(Installer.class.getName())
> > + .getDeclaredField("instrumentation");
> > + field.setAccessible(true);
> > + return (Instrumentation) field.get(null);
> > + } catch (Exception e) {
> > + throw null;
> > + }
> > + }
> > +
> > + private static void saveAgentJar(File agentFile) throws Exception {
> > + InputStream inputStream =
> Installer.class.getResourceAsStream('/' +
> Installer.class.getName().replace('.', '/') + ".class");
> > + if (inputStream == null) {
> > + return;
> > + }
> > + try {
> > + Manifest manifest = new Manifest();
> > +
> manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
> > + manifest.getMainAttributes().put(new
> Attributes.Name("Agent-Class"), Installer.class.getName());
> > + JarOutputStream jarOutputStream = new JarOutputStream(new
> FileOutputStream(agentFile), manifest);
> > + try {
> > + jarOutputStream.putNextEntry(new JarEntry('/' +
> Installer.class.getName().replace('.', '/') + ".class"));
> > + byte[] buffer = new byte[1024];
> > + int index;
> > + while ((index = inputStream.read(buffer)) != -1) {
> > + jarOutputStream.write(buffer, 0, index);
> > + }
> > + jarOutputStream.closeEntry();
> > + } finally {
> > + jarOutputStream.close();
> > + }
> > + } finally {
> > + inputStream.close();
> > + }
> > + }
> > +
> > /**
> > * Produces the toString string, only calling toString() on known
> types,
> > * which do not mutate the instance.
> > @@ -526,6 +612,15 @@
> >
> > static class MyDoubles4 {
> > private double f1, f2, f3, f4;
> > + }
> > +
> > + public static class Installer {
> > +
> > + private static volatile Instrumentation instrumentation;
> > +
> > + public static void agentmain(String agentArgs, Instrumentation
> inst) {
> > + instrumentation = inst;
> > + }
> > }
> >
> > }
> >
> >
> >
> > 2014-12-18 21:02 GMT+01:00 Aleksey Shipilev <aleksey.shipilev at oracle.com
> > <mailto:aleksey.shipilev at oracle.com>>:
> >
> > Hi Rafael, Serkan,
> >
> > On 12/17/2014 05:41 PM, Rafael Winterhalter wrote:
> > > But this other approach only works if VMSupport was loaded by the
> system
> > > ClassLoader where agents must be loaded from. Otherwise, the
> VMSupport that
> > > is the agent and the VMSupport that installs the agent are two
> different
> > > classes and the set INSTRUMENTATION field would belong to a
> different
> > > class. This is why I prefer the hack by adding an additional
> installer
> > > class that is minimal in byte size and does not carry any other
> class
> > > dependencies and inject this class. Also, I only access it by
> reflection in
> > > order to avoid these class identity issues. Might not be as
> relevant for
> > > JOL as I guess most people do not really use this from a servlet
> container
> > > or somewhere but I guess there might be corner cases (?).
> >
> > You will be suprised *where* people use JOL. Therefore, I would not
> like
> > to artificially limit the its applicability.
> >
> > I like Rafael's approach. Rafael, can you send the patch either in
> > attachment or inline on this list? OpenJDK ToU requires us to accept
> the
> > incoming changes on openjdk.java.net <http://openjdk.java.net>. You
> > seem to already have the OCA
> > signed, so we are in clear about attribution.
> >
> > Thanks,
> > -Aleksey.
> >
> >
>
>
>
More information about the jol-dev
mailing list