使用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);
}
那么如果想要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);
}