【发布时间】:2017-08-08 11:47:29
【问题描述】:
我知道这不是一个好的要求。但我现在需要这样做。
我需要替换Class.getResourceAsStream(String)的方法
但是ClassLoader.preDefineClass(String , ProtectionDomain)检查全名的类名是否以java.开头,如果是则抛出异常,不允许加载。
有没有办法绕过运行时安全检查而不是编译时?
更新
真正的需求是很多老项目需要迁移到新环境,因为这些项目有的可能已经过时,有的可能找不到源代码。我需要在新环境中模拟旧环境,以便这些古老的项目能够继续发挥作用。
Upadte (GhostCat)
我尝试了你给的方式。
类加载器类
public class ClassLoaderTest extends ClassLoader {
@Override
public InputStream getResourceAsStream(String name) {
System.out.println("getResourceAsStream " + name);
return new ByteArrayInputStream(new byte[]{1, 3, 5, 7, 9});
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
System.out.println("Load class " + name);
String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
InputStream is = getClass().getResourceAsStream(fileName);
if (is == null) {
return super.loadClass(name);
}
byte[] b = new byte[0];
try {
b = new byte[is.available()];
is.read(b);
} catch (IOException e) {
e.printStackTrace();
}
return defineClass(name, b, 0, b.length);
}
}
调用类
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
ClassLoaderTest classLoaderTest = new ClassLoaderTest();
Class clazz = Class.forName("com.Client", true, classLoaderTest);
Object client = clazz.newInstance();
Method method = clazz.getDeclaredMethod("method");
method.invoke(client);
}
客户端类
public class Client {
public void method() {
System.out.println(this.getClass().getResourceAsStream("aaa"));
System.out.println(Class.class.getResourceAsStream("bbb"));
System.out.println("".getClass().getResourceAsStream("ccc"));
}
}
它确实适用于 this.getClass().getResourceAsStream(String),但 Class.class.getResourceAsStream(String) / "".getClass().getResourceAsStream(String) 。因为我无法使用我的自定义 ClassLoader 加载类
名字以java.开头
【问题讨论】:
-
出于安全考虑,此功能已禁用。您可以扩展所需的类并在需要时调用自己的类,但无法进行替换。
-
为什么你认为你需要替换
Class.getResourceAsStream()?这就是你应该提出的问题。 -
@Kayaman 是的,这确实是我的问题。因为一个很老的项目已经迁移到新环境了,老项目早就没有维护了,现在正在尝试模拟一个和老项目一致的环境。
-
@RishiGoel 谢谢。这是一个非常古老的项目,但它实际上没用,但它不愿意扔掉它。估计有一部分项目可能一直找不到源代码
-
什么是
ClassLoader.preDefineClass(String, ProtectionDomain)?没有这种方法。
标签: java jvm javassist hotswap