您可以隨時使用ASM修補舊類。通過忽略clinit塊生成舊字節碼中的新類應該很容易。
import org.objectweb.asm.*;
import org.objectweb.asm.commons.EmptyVisitor;
import java.io.*;
public class ClinitKiller {
public static void main (String[] args) {
final InputStream input = ClinitKiller.class.getResourceAsStream(Test.class.getName() + ".class");
try {
final byte[] bytes = instrument(input);
FileOutputStream out = new FileOutputStream("/tmp/Test.class");
out.write(bytes);
out.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
public static byte[] instrument(InputStream is) throws IOException {
ClassReader reader = new ClassReader(is);
ClassWriter writer = new ClassWriter(0);
ClinitKillerClassAdapter classAdapter = new ClinitKillerClassAdapter(writer);
reader.accept(classAdapter, 0);
return writer.toByteArray();
}
}
class ClinitKillerClassAdapter extends ClassAdapter {
public ClinitKillerClassAdapter(final ClassVisitor cv) {
super(cv);
}
public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) {
if (name.equals("<clinit>")) {
return new EmptyVisitor();
}
return cv.visitMethod(access, name, desc, signature, exceptions);
}
}
這裏是之前和之後以下類:
public class Test {
private static final String value;
static {
System.out.println("Test static");
value = "test value";
}
public static void main(String[] args) {
System.out.println(value);
}
}
前:
javap -c Test
Compiled from "Test.java"
public class Test extends java.lang.Object{
public Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
3: getstatic #3; //Field value:Ljava/lang/String;
6: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
9: return
static {};
Code:
0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldC#5; //String Test static
5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: ldC#6; //String test value
10: putstatic #3; //Field value:Ljava/lang/String;
13: return
}
輸出:
測試靜態
測試值
一壓腳提升:
javap -c Test
Compiled from "Test.java"
public class Test extends java.lang.Object{
public Test();
Code:
0: aload_0
1: invokespecial #11; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #21; //Field java/lang/System.out:Ljava/io/PrintStream;
3: getstatic #23; //Field value:Ljava/lang/String;
6: invokevirtual #29; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
9: return
}
輸出:
空
來源
2013-01-23 10:12:03
jdb
我投票,但我認爲你應該提供示例 – CAMOBAP
會試試看,謝謝! – krisy