@
breadenglish 算是历史遗留原因,因为旧项目在不同环境下需要 hack 的方法不同。可以理解为新环境下是提供一种模拟环境,供老旧项目运行。
目前做过这样的尝试,通过 javassist 生成不检查类名安全检查以及 hack 过的 Class 字节码的 ClassLoader 对象,然后试图通过反射修改当前类加载器的父类加载器,以此绕过双亲委派机制,结果并不成功,程序运行直接输出 Exception in thread "main" 且没有退出,仿佛一种假死状态。代码如下:
```
public class JavassistHelp {
static ClassLoader hackClassLoader = new ClassLoader() {
private byte[] classBytecode = null;
private byte[] classBytecode() {
if (this.classBytecode == null) {
ClassPool classPool = ClassPool.getDefault();
try {
CtClass ordClass = classPool.get("java.lang.Class");
ordClass.defrost();
CtMethod ordMethod = ordClass.getDeclaredMethod("getResourceAsStream");
ordMethod.insertBefore("return new java.io.ByteArrayInputStream(new byte[]{1, 3, 5, 7, 9});");
this.classBytecode = ordClass.toBytecode();
} catch (NotFoundException e) {
e.printStackTrace();
} catch (CannotCompileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return classBytecode;
}
@
Override public Class<?> loadClass(String name) throws ClassNotFoundException {
try {
if ("java.lang.Class".equals(name)) {
System.err.println("loadClass hack");
return this.defineClass(name, this.classBytecode(), 0, this.classBytecode().length);
}
String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
InputStream is = getClass().getResourceAsStream(fileName);
if (is == null) {
return super.loadClass(name);
}
byte[] b = new byte[is.available()];
is.read(b);
return defineClass(name, b, 0, b.length);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
};
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
// 通过反射修改父类加载器
Field parent = ClassLoader.class.getDeclaredField("parent");
parent.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(parent, parent.getModifiers() & ~Modifier.FINAL);
parent.set(JavassistHelp.class.getClassLoader(), JavassistHelp.hackClassLoader);
System.err.println("load resource is " + String.class.getResourceAsStream("111"));
}
}
```