打开安全管理器导致ClassNotFoundException

时间:2014-10-23 07:10:25

标签: classloader classnotfoundexception securitymanager

这个演示,我想更好地理解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-startjetty-xml(我只是模拟码头模块名称):

enter image description here

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

0 个答案:

没有答案