这个演示,我想更好地理解AccessController.doPrivileged()。在jetty-xml
模块中,main()
方法具有以下代码:
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
try {
Properties properties = null;
}
...
}
}
我认为这是为了确保jetty-start
模块可以成功调用jetty-xml
模块。所以我写了一个简单的demo.But我有一个新问题,现在这个问题与Jetty无关。
我曾使用谷歌搜索相关问题,但大多数关于rmi.Following图是项目结构,有两个模块,jetty-start
和jetty-xml
(我只是模拟码头模块名称):
jetty-start
模块Main
类,首先调用XmlConfiguration#readFile()
,然后通过构造函数调用XmlConfiguration#readFileWithPrivilegedAction()
一个新的类加载器并反映。另外,运行Main
class,使用-Djava.security.policy=jetty-testXmlModulePrivileged.policy
vm args。
public class Main {
public static void main(String[] args) throws IOException, ReflectiveOperationException {
ClassLoader loader = getLoader();
Thread.currentThread().setContextClassLoader(loader);
Class<?> clazz = loader.loadClass("org.jetty.xml.XmlConfiguration");
System.setSecurityManager(new SecurityManager());
try {
System.out.println("invoke readFile().");
Method method = clazz.getMethod("readFile");
String lines = (String) method.invoke(null);
System.out.println("File Content: \n" + lines);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("/////////////////////////////////////////////////////////");
System.out.println();
try {
System.out.println("invoke readFileWithPrivilegedAction().");
Method method = clazz.getMethod("readFileWithPrivilegedAction");
String lines = (String) method.invoke(null);
System.out.println("File Content: \n" + lines);
} catch (Exception e) {
e.printStackTrace();
}
}
private static ClassLoader getLoader() throws IOException {
ClassLoader parent = Thread.currentThread().getContextClassLoader();
final String CLASSPATH_PATH = "E:\\Java\\workspace\\Test\\jetty-xml\\bin\\";
File bin = new File(CLASSPATH_PATH);
URL binUrl = bin.getCanonicalFile().toURI().toURL();
System.out.println("add classpath : " + binUrl);
URL[] urls = {binUrl};
ClassLoader loader = new StartClassLoader(urls, parent);
return loader;
}
private static class StartClassLoader extends URLClassLoader {
public StartClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}
}
}
jetty-xml
模块XmlConfiguration
类,一种方法是普通方法调用,另一种方法使用AccessController.doPrivileged
:
public class XmlConfiguration {
private final static String FOLDER_PATH = "E:\\Java\\workspace\\Test\\jetty-xml\\config\\";
private final static String FILENAME = "server.xml";
public static String readFile() throws IOException {
File fs = new File(FOLDER_PATH + FILENAME);
StringBuilder lines = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(
new FileInputStream(fs)))) {
String line = null;
while ((line = reader.readLine()) != null) {
lines.append(line);
}
}
return lines.toString();
}
/**
*/
public static String readFileWithPrivilegedAction() throws IOException {
String lines = AccessController.doPrivileged(new PrivilegedAction<String>() {
@Override
public String run() {
File fs = new File(FOLDER_PATH + FILENAME);
StringBuilder lines = new StringBuilder();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(fs)))) {
String line = null;
while ((line = reader.readLine()) != null) {
lines.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
return lines.toString();
}
});
return lines;
}
}
jetty-testXmlModulePrivileged.policy
是,允许jetty-xml
权限阅读server.xml
文件。
grant codebase "file:/E:/Java/workspace/Test/jetty-xml/bin"
{
permission java.io.FilePermission "E:\\Java\\workspace\\Test\\jetty-xml\\config\\server.xml", "read,write";
};
最后我运行Main
,我能理解的第一个例外,它没有权限(例如,调用readFile()
方法),而不是在AccessController.doPrivileged
中运行,但是第二个例外,我有点困惑(例如调用readFileWithPrivilegedAction()
方法):
invoke readFile().
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jetty.start.Main.main(Main.java:23)
Caused by: java.security.AccessControlException: access denied ("java.io.FilePermission" "E:\Java\workspace\Test\jetty-xml\config\server.xml" "read")
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:372)
at java.security.AccessController.checkPermission(AccessController.java:559)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
at java.lang.SecurityManager.checkRead(SecurityManager.java:888)
at java.io.FileInputStream.<init>(FileInputStream.java:135)
at org.jetty.xml.XmlConfiguration.readFile(XmlConfiguration.java:19)
... 5 more
/////////////////////////////////////////////////////////
invoke readFileWithPrivilegedAction().
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jetty.start.Main.main(Main.java:35)
Caused by: java.lang.NoClassDefFoundError: org/jetty/xml/XmlConfiguration$1
at org.jetty.xml.XmlConfiguration.readFileWithPrivilegedAction(XmlConfiguration.java:34)
... 5 more
Caused by: java.lang.ClassNotFoundException: org.jetty.xml.XmlConfiguration$1
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
... 6 more
我有一个新的类加载器构造函数,添加jetty-xml
bin类路径,然后将当前线程类加载器设置为这个新的类加载器,我认为这个类加载器可以加载org.jetty.xml.XmlConfiguration$1
。如果我修改{{1}这是好的:
Main
这类似于Tomcat的Class<?> clazz = loader.loadClass("org.jetty.xml.XmlConfiguration");
loader.loadClass("org.jetty.xml.XmlConfiguration$1");
class.Preload some class。但是,为什么不抛出SecurityClassLoad
?