我遇到了 Tomcat servlet 的一些奇怪的访问控制异常(当它尝试绑定到 RMI 服务器时)。我在没有安全管理器的情况下运行,并且整个应用程序以前在基本相同的设置下运行良好。
这是我所在的 Web 应用程序的类文件夹的 java.io.FilePermission 访问权限被拒绝。当我将 RMI 存根重新绑定到 RMI 注册表(这是后我访问了同一个 webapp 中的其他一些类,并且在导出存根并找到注册表之后;做了一些日志消息来证明这一点)。任何帮助都将非常有用,因为我现在对这个问题束手无策了……
更新:好的,取得了一些进展(此更新覆盖了以前的假设)。这与 RMI 注册表的代码库访问以及 OpenJDK 的一些怪癖有关。
当我将服务器绑定到注册表时,它会尝试通过它认为的代码库来访问相关类。看来,无论注册表使用什么隐秘的 RMI 魔法来获取代码库位置,它都无法获取 JVM 属性中的代码库位置,而是尝试在 Web 应用程序的类路径中查找(??)。
理由(!):这曾经在代码库的文件 URL 下工作得很好(没有 Java 安全策略)。我在 Tomcat 之外测试了 RMI 服务器设置(只是作为 POJO),它与HTTP 网址但不是文件错误。后者给出与 Tomcat 相同的访问权限错误,但显示它试图访问这个特定的文件位置(与 Tomcat 不同,Tomcat 尝试访问完全不同的位置)。我怀疑文件 URL 失败可能是由于 OpenJDK 和 Sun JDK 之间的差异造成的。(我之前使用的是 Sun 的;我刚想起来。)
然而,当我尝试使用 Tomcat 设置的工作 HTTP URL(确保为它提供服务的 Web 服务器与 Tomcat 位于不同的端口上)时,它仍然尝试访问 webapp 的类路径区域时失败。我已在 servlet 代码中确认 java.rmi.server.codebase 属性设置正确(因此它已成功传递到 servlet 代码)。也许是 OpenJDK rmiregistry 中存在错误(似乎不太可能)?
这是否有助于人们有更多的想法?将其放在 StackOverflow 上是否更好(我认为有人可能会争论将其放在任何一个位置)?
使用 Tomcat 6.0.24 本地环境,由 Ubuntu 10.04 x64 上的 tomcat6-instance-create cmd 使用 OpenJDK 1.6.0_20 创建。(所有 Ubuntu 10.04 默认设置。)
异常跟踪如下:
simHAWSER.core.exceptions.HAWSER_RMI_ConfigurationException: Error setting up observer gateway server HAWSER_ObserverGateway
at simHAWSER.core.internal.yawlInterface.HAWSER_ObserverGateway.announceEngineInitialised(HAWSER_ObserverGateway.java:1404)
at org.yawlfoundation.yawl.engine.ObserverGatewayController$8.run(ObserverGatewayController.java:278)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:636)
Caused by: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: access to class loader denied
at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:419)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:267)
at sun.rmi.transport.Transport$1.run(Transport.java:177)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:553)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:808)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:667)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:636)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:273)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:251)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:377)
at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
at simHAWSER.core.internal.yawlInterface.HAWSER_ObserverGateway.announceEngineInitialised(HAWSER_ObserverGateway.java:1400)
... 4 more
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: access to class loader denied
at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:409)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:267)
at sun.rmi.transport.Transport$1.run(Transport.java:177)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:553)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:808)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:667)
... 3 more
Caused by: java.lang.ClassNotFoundException: access to class loader denied
at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:603)
at java.rmi.server.RMIClassLoader$2.loadProxyClass(RMIClassLoader.java:646)
at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:311)
at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:255)
at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1548)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1510)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1749)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1346)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:368)
... 12 more
Caused by: java.security.AccessControlException: access denied (java.io.FilePermission /home/rigsby/Build/yawl/r1803/tomcat6/webapps/yawl/WEB-INF/classes/- read)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:393)
at java.security.AccessController.checkPermission(AccessController.java:553)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
at sun.rmi.server.LoaderHandler$Loader.checkPermissions(LoaderHandler.java:1173)
at sun.rmi.server.LoaderHandler$Loader.access$000(LoaderHandler.java:1127)
at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:569)
... 20 more
原始 simHAWSER 类是我的应用程序(作为 yawl webapp 的一部分运行)。如果有任何影响,我的代码将作为 webapp lib 目录中的单独 JAR 运行,并由 yawl servlet(部署到普通类目录)调用。
在半绝望的情况下,我尝试启动 Tomcat和安全管理器(授予此 Web 应用程序所有权限),但这在读取我的 catalina.policy 文件时导致了一些奇怪的“空 KeyStore 名称”异常(我刚刚从这里)无论如何,我知道它起作用了(并且应该工作)而没有安全保障,所以不想在这个方向上做徒劳无功的事情:-)
如果有人想了解更多详细信息,请告诉我。
PS 想要添加 RMI 标签(或 rmiregistry 来匹配堆栈溢出),但没有它的代表:-(如果有人想添加它,那就太好了。
答案1
OK,解决了。问题曾是使用 OpenJDK 而不是 Sun Java。OpenJDKrmiregistry
实现不喜欢文件 URL(访问异常),当尝试访问 Tomcat webapp 的 codebase 属性时,它不知何故无法正确查看它(假设与 Tomcat 中使用的每个 webapp 类加载器混淆有关)。
切换到 Sunrmiregistry
实现(即使保留对 Tomcat 的 OpenJDK 使用)意味着它可以正常工作。如果我找不到任何 OpenJDK 错误,我会提出一个并在此处链接到它以确保完整性。
我怀疑 OpenJDK 的文件 URL 问题是由于不同的默认(没有明确的 java 策略)安全设置造成的,我可以使用明确的策略文件来使其工作......
希望这可以为其他人提供帮助,因为这确实是一个令人困惑的问题。