JAVA RMI遠端呼叫Socket服務異常--安全管理器
背景要求:定時監控遠端主機上mongodb資料庫記憶體使用的情況,當記憶體使用過大時暫停邏輯處理執行緒後啟動記憶體空間的釋放處理執行緒,釋放完成後再啟動邏輯處理執行緒。
作業系統:CentOS 64bit (Linux)
步驟(程式碼省略):
1.建立Socket遠端伺服器
2.建立客戶端
配置:
#查詢物件stub埠
RMI_PORT=9902
#服務埠
RMI_SERV_RMI_PORT=9903
#註冊服務地址埠要和查詢物件stub埠一致
RMI_URL=rmi://192.168.0.118:9902/MongoServer
#繫結IP
RMI_IP=192.168.0.118
#檢查記憶體shell
RMI_MEMQUERY_COMMAND=sh /home/test/BI/smartshow14/MongoDBRMIServer/memquery.sh
#釋放記憶體shell
RMI_MEMFREE_COMMAND=sh /home/test/BI/smartshow14/MongoDBRMIServer/memclear.sh
#釋放記憶體容量閥值,單位M
RMI_MEM_CAPACITY_LIMIT=3000
3.啟動伺服器
客戶端執行緒通過 rmi://192.168.0.118:9902/MongoServer 訪問時出現異常:
--定時掃描MONGODB記憶體執行緒--:開始執行!
java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.lang.ClassNotFoundException: com.linkage.iface.IMongoDBScan (no security manager: RMI class loader disabled)
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at java.rmi.Naming.lookup(Naming.java:84)
at com.linkage.querytool.QueryRMICaller.ramCapacityScan(QueryRMICaller.java:87)
at com.linkage.querytool.MongoDBARMScanThread$TimerWorkTask.run(MongoDBARMScanThread.java:94)
at java.util.TimerThread.mainLoop(Timer.java:512)
at java.util.TimerThread.run(Timer.java:462)
Caused by: java.lang.ClassNotFoundException: com.linkage.iface.IMongoDBScan (no security manager: RMI class loader disabled)
at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:535)
at java.rmi.server.RMIClassLoader$2.loadProxyClass(RMIClassLoader.java:628)
at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:294)
at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:238)
at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1530)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1492)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
... 6 more
--定時掃描MONGODB記憶體執行緒--:處理結束!
=======================================================================================================
--定時掃描MONGODB記憶體執行緒--:開始執行!
java.security.AccessControlException: access denied (java.net.SocketPermission 192.168.0.118:9902 connect,resolve)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:374)
at java.security.AccessController.checkPermission(AccessController.java:546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.SecurityManager.checkConnect(SecurityManager.java:1034)
at java.net.Socket.connect(Socket.java:524)
at java.net.Socket.connect(Socket.java:478)
at java.net.Socket.<init>(Socket.java:375)
at java.net.Socket.<init>(Socket.java:189)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:22)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:128)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:595)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:198)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:184)
at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:322)
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at java.rmi.Naming.lookup(Naming.java:84)
at com.linkage.querytool.QueryRMICaller.ramCapacityScan(QueryRMICaller.java:89)
at com.linkage.querytool.MongoDBARMScanThread$TimerWorkTask.run(MongoDBARMScanThread.java:94)
at java.util.TimerThread.mainLoop(Timer.java:512)
at java.util.TimerThread.run(Timer.java:462)
--定時掃描MONGODB記憶體執行緒--:處理結束!
============================================================================================================
--定時掃描MONGODB記憶體執行緒--:開始執行!
java.security.AccessControlException: access denied (java.lang.RuntimePermission createSecurityManager)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:374)
at java.security.AccessController.checkPermission(AccessController.java:546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.SecurityManager.<init>(SecurityManager.java:282)
at java.rmi.RMISecurityManager.<init>(RMISecurityManager.java:45)
at com.linkage.querytool.QueryRMICaller.ramCapacityScan(QueryRMICaller.java:88)
at com.linkage.querytool.MongoDBARMScanThread$TimerWorkTask.run(MongoDBARMScanThread.java:94)
at java.util.TimerThread.mainLoop(Timer.java:512)
at java.util.TimerThread.run(Timer.java:462)
--定時掃描MONGODB記憶體執行緒--:處理結束!
==========================================================================================================
以上異常都有可能出現,通過以下方式可解除問題:
1.在客戶端程式前開啟安全管理器:
try {
System.setSecurityManager(new java.rmi.RMISecurityManager());
mds = (IMongoDBScan) Naming.lookup(urlStr);
} catch (MalformedURLException e) {
//..........
}
2.修改/usr/java/jdk1.6.0_21/jre/lib/security/java.policy後重啟
grant {
permission java.security.AllPermission;
}