浅谈Java中DefineClass方法以及ClassLoader

反射调用ClassLoader类的defineClass方法直接根据字节数组定义一个类

package org.hope;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

public class Main2{
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method mdDefineClass = ClassLoader.class
                .getDeclaredMethod("defineClass",String.class,byte[].class,int.class,int.class);
        mdDefineClass.setAccessible(true);
        System.out.println(mdDefineClass);

        byte[] classBytes = new byte[] {-54,-2,-70,-66,0,0,0,52,0,29,10,0,6,0,15,9,0,16,0,17,8,0,18,10,0,19,0,20,7,0,21,7,0,22,1,0,6,60,105,110,105,116,62,1,0,3,40,41,86,1,0,4,67,111,100,101,1,0,15,76,105,110,101,78,117,109,98,101,114,84,97,98,108,101,1,0,4,109,97,105,110,1,0,22,40,91,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,41,86,1,0,10,83,111,117,114,99,101,70,105,108,101,1,0,9,77,97,105,110,46,106,97,118,97,12,0,7,0,8,7,0,23,12,0,24,0,25,1,0,11,104,101,108,108,111,32,119,111,114,108,100,7,0,26,12,0,27,0,28,1,0,16,99,111,109,47,115,117,110,116,111,119,110,47,77,97,105,110,1,0,16,106,97,118,97,47,108,97,110,103,47,79,98,106,101,99,116,1,0,16,106,97,118,97,47,108,97,110,103,47,83,121,115,116,101,109,1,0,3,111,117,116,1,0,21,76,106,97,118,97,47,105,111,47,80,114,105,110,116,83,116,114,101,97,109,59,1,0,19,106,97,118,97,47,105,111,47,80,114,105,110,116,83,116,114,101,97,109,1,0,7,112,114,105,110,116,108,110,1,0,21,40,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,41,86,0,33,0,5,0,6,0,0,0,0,0,2,0,1,0,7,0,8,0,1,0,9,0,0,0,29,0,1,0,1,0,0,0,5,42,-73,0,1,-79,0,0,0,1,0,10,0,0,0,6,0,1,0,0,0,2,0,9,0,11,0,12,0,1,0,9,0,0,0,37,0,2,0,1,0,0,0,9,-78,0,2,18,3,-74,0,4,-79,0,0,0,1,0,10,0,0,0,10,0,2,0,0,0,4,0,8,0,5,0,1,0,13,0,0,0,2,0,14};

        String className = "com.suntown.Main";
        Class c1 = (Class)mdDefineClass.invoke(ClassLoader.getSystemClassLoader(),new Object[]{
                className,classBytes,0,classBytes.length
        });

        Class c2 = (Class)mdDefineClass.invoke(new URLClassLoader(new URL[]{}),new Object[]{
                className,classBytes,0,classBytes.length
        });
        System.out.println("c1.class=" +c1.getClassLoader()+"\nc2.class="+c2.getClassLoader() + "\n"+(c1 == c2));
    }
}

运行结果如下

 

类c1,c2分别由 ClassLoader.getSystemClassLoader(),URLClassLoader 两个不同的类加载器加载同一个字节数组而得到的,所以比较 c1 == c2 返回false,所以类的唯一性的取决于定义该类的classloader

上述代码实现了 直接在内存中去定义一个java类的功能,没有引用一个新的用户定义的classloader。这种优点可以结合javassist进行字节码插桩的时候发挥出作用。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天水麒麟姜伯约

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值