什么是 premain() 以及如何调用它?
What is premain() and how does it get called?
我从未听说过 premain
,我觉得问这个问题有点愚蠢,但 the answer of this post 建议运行它以获得 Instrumentation
对象。
但是该函数是如何被调用的,或者我如何让它被调用?
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);
}
}
premain
是与 java.lang.instrument
包关联的机制,用于加载 "Agents",从而在 Java 程序中更改字节码。
该机制在 java.lang.instrument
documentation 中进行了解释。
要点是 "agent" 部署在一个 jar 中,并且该 jar 在其清单中有一个特殊条目,它告诉检测包在哪里寻找 premain 方法。你引用的来源应该是一个简单的代理。
最小可运行示例
GitHub 上游: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()));
}
}
生成文件
all:
javac *.java
jar -cfm Sizeof.jar META-INF/MANIFEST.MF Sizeof.class
java -ea -javaagent:Sizeof.jar Main
示例输出:
Object
16
/""
24
/"abc"
24
int[0]
16
int[10]
56
OneInt
16
TwoInts
24
IntArray0
16
IntArray10
16
在 Ubuntu 16.10、Java HotSpot 1.8 中测试。0_92.
我从未听说过 premain
,我觉得问这个问题有点愚蠢,但 the answer of this post 建议运行它以获得 Instrumentation
对象。
但是该函数是如何被调用的,或者我如何让它被调用?
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);
}
}
premain
是与 java.lang.instrument
包关联的机制,用于加载 "Agents",从而在 Java 程序中更改字节码。
该机制在 java.lang.instrument
documentation 中进行了解释。
要点是 "agent" 部署在一个 jar 中,并且该 jar 在其清单中有一个特殊条目,它告诉检测包在哪里寻找 premain 方法。你引用的来源应该是一个简单的代理。
最小可运行示例
GitHub 上游: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()));
}
}
生成文件
all:
javac *.java
jar -cfm Sizeof.jar META-INF/MANIFEST.MF Sizeof.class
java -ea -javaagent:Sizeof.jar Main
示例输出:
Object
16
/""
24
/"abc"
24
int[0]
16
int[10]
56
OneInt
16
TwoInts
24
IntArray0
16
IntArray10
16
在 Ubuntu 16.10、Java HotSpot 1.8 中测试。0_92.