有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

新InitialContext()上的java无限递归

我正在尝试为JavaSE控制台应用程序设置JNDI

我有以下代码:

public class FooMain {

    public static void main (String args[]) throws NamingException {
        Context context = new InitialContext();
        context.bind("foo", "bar");
    }
}

…上下文工厂定义为:

public class MyContextFactory implements InitialContextFactory {

    private static Hashtable store = new Hashtable();

    @Override
    public Context getInitialContext(Hashtable environment) throws NamingException {
        return new InitialContext() {

            @Override
            public void bind(String name, Object obj) {
                store.put(name, obj);
            }

            @Override
            public Object lookup(String name) {
                return store.get(name);
            }    
        };
    }
}

当我使用以下命令调用我的FooMain类时:

java -Djava.naming.factory.initial=MyContextFactory -cp ... FooMain

我得到无限递归和最终的StackOverflow异常:

Exception in thread "main" java.lang.StackOverflowError
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.naming.internal.VersionHelper12.getContextClassLoader(VersionHelper12.java:185)
at com.sun.naming.internal.ResourceManager.getApplicationResources(ResourceManager.java:549)
at com.sun.naming.internal.ResourceManager.getInitialEnvironment(ResourceManager.java:244)
at javax.naming.InitialContext.init(InitialContext.java:240)
at javax.naming.InitialContext.<init>(InitialContext.java:192)
at MyContextFactory$1.<init>(MyContextFactory.java:20)
at MyContextFactory.getInitialContext(MyContextFactory.java:20)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.init(InitialContext.java:244)
at javax.naming.InitialContext.<init>(InitialContext.java:192)
at MyContextFactory$1.<init>(MyContextFactory.java:20)
at MyContextFactory.getInitialContext(MyContextFactory.java:20)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.init(InitialContext.java:244)
at javax.naming.InitialContext.<init>(InitialContext.java:192)
at MyContextFactory$1.<init>(MyContextFactory.java:20)
at MyContextFactory.getInitialContext(MyContextFactory.java:20)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.init(InitialContext.java:244)
at javax.naming.InitialContext.<init>(InitialContext.java:192)
...

我可以创建一个“环境”哈希表,将MyContextFactory类的名称放在那里(在“java.naming.factory.initial”键下),然后使用接受哈希表环境的构造函数创建InitialContext,从而使代码正常工作:

Context context = new InitialContext(environment);

但我的问题是:如何使用无参数构造函数并在调用JVM时使用“-Djava.naming.factory.initial”提供工厂类的名称来实现这一点


共 (1) 个答案

  1. # 1 楼答案

    感谢Jim Garrison的建议,以下是答案。 问题的关键是在MyContext类的构造函数中调用super(true);

    class MyContext extends InitialContext {
    
        private Hashtable store;
    
        public MyContext(Hashtable store) throws NamingException {
            super(true);
            this.store = store;
        }
    
        @Override
        public void bind(String name, Object obj) {
            store.put(name, obj);
        }
    
        @Override
        public Object lookup(String name) {
            return store.get(name);
        }    
    
    }
    
    
    
    public class FooMain {
    
        private static final int    ANSWER    = 42;
        private static final String JNDI_NAME = "/config/theAnswerToEverything";
    
        public static void main (String args[]) throws NamingException {
            Context context = new InitialContext();
            putInContext(                    JNDI_NAME, ANSWER);
    
            int answer = retrieveFromContext(JNDI_NAME);
            Assert.assertEquals(ANSWER, answer);
            System.out.printf("%d\n", answer);
        }
    
    
        private static void putInContext(final String key, final Object value) throws NamingException {
            Context context = new InitialContext();
            context.bind(key, value);
        }
    
        private static int retrieveFromContext(final String key) throws NamingException {
            Context context = new InitialContext();
            return (int) context.lookup(key);
        }
    }
    
    
    public class MyContextFactory implements InitialContextFactory {
    
        private static Hashtable store = new Hashtable();
    
        /*
          Do not confuse [store] with [environment]. They serve different
          purposes.
         */
    
        @Override
        public Context getInitialContext(Hashtable environment) throws NamingException {
            return new MyContext(store);
        }
    }
    

    从命令行调用:

    $ java -Djava.naming.factory.initial=MyContextFactory -cp [actual classpath] FooMain
    42