系统类加载器动态加载

使用ASM动态编码时,只能获得动态的字节码,但是如果想要让JVM知道,必须要使用加载器来完成.而通常会自定义ClassLoader进行加载.那么如果是系统类加载器加载的类,无法引用自定义加载器加载的类.

那么如果想要ASM生成的字节码,然后通过系统类加载进行加载,那么就没有上面的问题了.

而JVM基于安全考虑,是不允许在未经许可而是用系统类加载器的.在开源项目javassist和ASM中都是通过以下办法来实现用系统类加载器加载动态字节码.

private static Method DEFINE_CLASS;
private static final ProtectionDomain PROTECTION_DOMAIN;
   
static {
        PROTECTION_DOMAIN = (ProtectionDomain)AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                return ReflectUtils.class.getProtectionDomain();
            }
        });
       
        AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                try {
                    Class loader = Class.forName("java.lang.ClassLoader"); // JVM crash w/o this
                    DEFINE_CLASS = loader.getDeclaredMethod("defineClass",
                                                            new Class[]{ String.class,
                                                                         byte[].class,
                                                                         Integer.TYPE,
                                                                         Integer.TYPE,
                                                                         ProtectionDomain.class });
                    DEFINE_CLASS.setAccessible(true);
                } catch (ClassNotFoundException e) {
                    throw new CodeGenerationException(e);
                } catch (NoSuchMethodException e) {
                    throw new CodeGenerationException(e);
                }
                return null;
            }
        });
    }
   
    public static Class defineClass(String className, byte[] b, ClassLoader loader) throws Exception {
        Object[] args = new Object[]{className, b, new Integer(0), new Integer(b.length), PROTECTION_DOMAIN };
        return (Class)DEFINE_CLASS.invoke(loader, args);
    }

你可能感兴趣的:(jvm)