Java-ASM

简介:

我们知道Java是静态语言,而python、ruby是动态语言,Java程序一旦写好很难在运行时更改类的行为,而python、ruby可以。

不过基于bytecode层面上我们可以做一些手脚,来使Java程序多一些灵活性和Magic,ASM就是这样一个应用广泛的开源库。

ASMisaJavabytecodemanipulationframework.Itcanbeusedtodynamicallygeneratestubclassesorotherproxyclasses,

directlyinbinaryform,ortodynamicallymodifyclassesatloadtime,i.e.,justbeforetheyareloadedintotheJavaVirtualMachine.

ASM完成了BCEL和SERP同样的功能,但ASM

只有30多k,而后两者分别是350k和150k。apache真是越来越过气了。

让我们来看一个ASM的简单例子Helloworld.java,它生成一个Example类和一个main方法,main方法打印"Helloworld!"语句:

Java代码

1.importjava.io.FileOutputStream;

2.importjava.io.PrintStream;

3.importorg.objectweb.asm.ClassWriter;

4.importorg.objectweb.asm.MethodVisitor;

5.importorg.objectweb.asm.Opcodes;

6.importorg.objectweb.asm.Type;

7.importorg.objectweb.asm.commons.GeneratorAdapter;

8.importorg.objectweb.asm.commons.Method;

9.

10.publicclassHelloworldextendsClassLoaderimplementsOpcodes{

11.

12.public staticvoid main(finalStringargs[])throwsException{

13.

14.//createsaClassWriterfortheExamplepublicclass,

15.//whichinheritsfromObject

16.

17.ClassWriter cw = newClassWriter(0);

18.cw.visit(V1_1,ACC_PUBLIC,"Example",null,"java/lang/Object",null);

19.MethodVisitormw=cw.visitMethod(ACC_PUBLIC,"<init>","()V",null,

20.null);

21.mw.visitVarInsn(ALOAD,0);

22.mw.visitMethodInsn(INVOKESPECIAL,"java/lang/Object","<init>","()V");

23.mw.visitInsn(RETURN);

24.mw.visitMaxs(1,1);

25.mw.visitEnd();

26.mw=cw.visitMethod(ACC_PUBLIC+ACC_STATIC,"main",

27."([Ljava/lang/String;)V",null,null);

28.mw.visitFieldInsn(GETSTATIC,"java/lang/System","out",

29."Ljava/io/PrintStream;");

30.mw.visitLdcInsn("Helloworld!");

31.mw.visitMethodInsn(INVOKEVIRTUAL,"java/io/PrintStream","println",

32."(Ljava/lang/String;)V");

33.mw.visitInsn(RETURN);

34.mw.visitMaxs(2,2);

35.mw.visitEnd();

36.byte[]code=cw.toByteArray();

37.FileOutputStreamfos=newFileOutputStream("Example.class");

38.fos.write(code);

39.fos.close();

40.Helloworldloader=newHelloworld();

41.ClassexampleClass=loader

42..defineClass("Example",code,0,code.length);

43.exampleClass.getMethods()[0].invoke(null,newObject[]{null});

 

44.//------------------------------------------------------------------------

45.//SameexamplewithaGeneratorAdapter(moreconvenientbutslower)

46.//------------------------------------------------------------------------

47.

48.cw=newClassWriter(ClassWriter.COMPUTE_MAXS);

49.cw.visit(V1_1,ACC_PUBLIC,"Example",null,"java/lang/Object",null);

50.Methodm=Method.getMethod("void<init>()");

51.GeneratorAdaptermg=newGeneratorAdapter(ACC_PUBLIC,m,null,null,

52.cw);

53.mg.loadThis();

54.mg.invokeConstructor(Type.getType(Object.class),m);

55.mg.returnValue();

56.mg.endMethod();

57.m=Method.getMethod("voidmain(String[])");

58.mg=newGeneratorAdapter(ACC_PUBLIC+ACC_STATIC,m,null,null,cw);

59.mg.getStatic(Type.getType(System.class),"out",Type

60..getType(PrintStream.class));

61.mg.push("Helloworld!");

62.mg.invokeVirtual(Type.getType(PrintStream.class),Method

63..getMethod("voidprintln(String)"));

64.mg.returnValue();

65.mg.endMethod();

66.cw.visitEnd();

67.code=cw.toByteArray();

68.loader=newHelloworld();

69.exampleClass=loader.defineClass("Example",code,0,code.length);

70.exampleClass.getMethods()[0].invoke(null,newObject[]{null});

71.}

72.}

 

我们看到上面的例子分别使用ASM的MethodVisitor和GeneratorAdapter两种方式来动态生成Example类并调用打印语句。

 

相关文章
|
安全 算法 Java
从零开发基于ASM字节码的Java代码混淆插件XHood
因在公司负责基础框架的开发设计,所以针对框架源代码的保护工作比较重视,之前也加入了一系列保护措施,例如自定义classloader加密保护,授权license保护等,但都是防君子不防小人,安全等级还比较低,经过调研各类加密混淆措施后,决定自研混淆插件,自主可控,能够贴合实际情况进行定制化,达到框架升级后使用零感知,零影响
140 1
从零开发基于ASM字节码的Java代码混淆插件XHood
|
6月前
|
存储 Java 编译器
使用ASM来书写Java代码
使用ASM来书写Java代码
51 0
|
7月前
|
存储 Java
【Java】How Java Memory Works
【Java】How Java Memory Works
36 0
【Java】How Java Memory Works
|
7月前
|
算法 Java 编译器
java asm、cglib
java asm、cglib
75 0
|
Java Nacos 开发者
Nacos无法启动详解:Please set the JAVA_HOME variable in your environment, We need java(x64) jdk8 or later
Nacos无法启动详解:Please set the JAVA_HOME variable in your environment, We need java(x64) jdk8 or later
3214 1
[ASM教程]#2生成类
使用classWriter生成类
70 0
|
Java 数据库连接 API
【Java基础】Java SPI 一 之SPI(Service Provider Interface)进阶& AutoService
【Java基础】Java SPI 一 之SPI(Service Provider Interface)进阶& AutoService
|
Java
Java报错:Cause: java.io.NotSerializableException: xxx 解决方案
原因是实体类没有开启序列化接口导致的 开启实体类序列化接口即可:
274 0
|
Java 编译器 测试技术
使用 Java ASM 替换字符串常量
具体来说,这个区块链是 Neo N3 区块链,其中 Java 的语言支持由 Neow3j 这个库提供。这个库允许开发者使用任意 JVM 语言开发合约,并根据最终编译的 Java 字节码生成 Neo 的可执行合约。因此上文提到的合约就是使用 Java 开发的,没有用 Kotlin 的原因就是怕翻车。
401 0
|
算法 Java 调度
Java Runtime Data Area | Java Debug 笔记
Java Runtime Data Area | Java Debug 笔记