我的应用程序有这个自定义类加载器:
JarByteClassloader loader = new JarByteClassloader(jar);
Class c = loader.loadClass(classToLoad);
Thread.currentThread().setContextClassLoader(loader);
JarEntryObject jarEntry = (JarEntryObject) c.newInstance();
我想问是否可以限制自定义类加载器加载的实例对特定类的访问?
因此,例如,System.getProperty()
或 System.getenv()
应该失败。通过什么方式可以做到这一点?
最佳答案
虽然对于这种情况,SecurityManager 可能是最合适的(尽管自 Java 17 起它已被弃用并标记为删除而无需替换),但实际上您可以通过类加载器限制对其他类的访问。
这可以通过重写类加载器的 loadClass
方法来完成。
有必要了解类加载器的委托(delegate)模型来限制它:
The ClassLoader class uses a delegation model to search for classes and resources. Each instance of ClassLoader has an associated parent class loader. When requested to find a class or resource, a ClassLoader instance will delegate the search for the class or resource to its parent class loader before attempting to find the class or resource itself. The virtual machine's built-in class loader, called the "bootstrap class loader", does not itself have a parent but may serve as the parent of a ClassLoader instance.
loadClass
方法的作用如下:
Loads the class with the specified binary name. The default implementation of this method searches for classes in the following order:
Invoke findLoadedClass(String) to check if the class has already been loaded.
Invoke the loadClass method on the parent class loader. If the parent is null the class loader built-in to the virtual machine is used, instead.
Invoke the findClass(String) method to find the class.
https://docs.oracle.com/javase/8/docs/api/java/lang/ClassLoader.html
因此,如果我们重写findClass
,则仅当父类加载器无法加载/查找该类时才会调用我们的代码。但我们想要拦截所有加载的类,因此我们需要重写 loadClass
:
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)) {
if (allowDelegateLoadingOf(name)) {
System.out.println("Delegate loading of " + name + " to parent class loader.");
return super.loadClass(name);
}
System.out.println("Prohibit class from delegating: " + name);
return findClass(name);
}
}
在这种情况下,allowDelegateLoadingOf 只是一个简单的 boolean 方法,用于确定是否应委托(delegate)类并因此加载或不加载。这可以通过简单地根据白名单或黑名单包/类列表检查类名来完成。
关于java - 自定义类加载器来限制对类的访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59998928/