33

I have never heard of a premain and I feel a little stupid to ask but the answer of this post suggests to run it in order to get the Instrumentation object.

But how does that function get called or how do I make it getting called?

package playground;
import java.lang.instrument.Instrumentation;

public class ObjectSizeFetcher {
    private static Instrumentation instrumentation;

    public static void premain(String args, Instrumentation inst) {
        instrumentation = inst;
    }

    public static long getObjectSize(Object o) {
        return instrumentation.getObjectSize(o);
    }
}
cнŝdk
  • 31,391
  • 7
  • 56
  • 78
Stefan Falk
  • 23,898
  • 50
  • 191
  • 378
  • 2
    The answer to your question is on [this page](http://docs.oracle.com/javase/7/docs/api/java/lang/instrument/package-summary.html) – Dawood ibn Kareem Jan 08 '15 at 23:55
  • 1
    This source code has everything: https://www.javacodegeeks.com/2015/09/java-agents.html – dkb Jan 17 '19 at 11:37

2 Answers2

22

The premain is a mechanism associated with the java.lang.instrument package, used for loading "Agents" which make byte-code changes in Java programs.

The mechanism is explained in the java.lang.instrument documentation.

The gist of it is that the "agent" is deployed in a jar, and that jar has a special entry in its manifest, that tells the instrumentation package where to look for the premain method. The source you quoted is supposed to be a simple agent.

RealSkeptic
  • 33,993
  • 7
  • 53
  • 79
13

Minimal runnable example

GitHub upstream: https://github.com/cirosantilli/java-cheat/tree/d73d2786cad458973a6b46bc98b9faabae65f3e1/instrument

META-INF/MANIFEST.MF

Premain-Class: Sizeof

Sizeof.java

import java.lang.instrument.Instrumentation;

final public class Sizeof {
    private static Instrumentation instrumentation;

    public static void premain(String args, Instrumentation inst) {
        instrumentation = inst;
    }

    public static long sizeof(Object o) {
        return instrumentation.getObjectSize(o);
    }
}

Main.java

final public class Main {
    public static void main(String [] args) {
        System.out.println("Object");
        System.out.println(Sizeof.sizeof(new Object()));

        System.out.println("/\"\"");
        System.out.println(Sizeof.sizeof(""));

        System.out.println("/\"abc\"");
        System.out.println(Sizeof.sizeof("abc"));

        System.out.println("int[0]");
        System.out.println(Sizeof.sizeof(new int[0]));

        System.out.println("int[10]");
        System.out.println(Sizeof.sizeof(new int[10]));

        class OneInt {
            public int i;
        }
        System.out.println("OneInt");
        System.out.println(Sizeof.sizeof(new OneInt()));

        class TwoInts {
            public int i;
            public int j;
        }
        System.out.println("TwoInts");
        System.out.println(Sizeof.sizeof(new TwoInts()));

        class IntArray0 {
            int[] i = new int[0];
        }
        System.out.println("IntArray0");
        System.out.println(Sizeof.sizeof(new IntArray0()));

        class IntArray10 {
            int[] i = new int[10];
        }
        System.out.println("IntArray10");
        System.out.println(Sizeof.sizeof(new IntArray10()));
    }
}

Makefile

all:
    javac *.java
    jar -cfm Sizeof.jar META-INF/MANIFEST.MF Sizeof.class
    java -ea -javaagent:Sizeof.jar Main

Sample output:

Object
16
/""
24
/"abc"
24
int[0]
16
int[10]
56
OneInt
16
TwoInts
24
IntArray0
16
IntArray10
16

Tested in Ubuntu 16.10, Java HotSpot 1.8.0_92.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985