坑爹的RMI Socket Facotry

因爲產品安全的需求,需要將之前老代碼的RMI服務端口綁定到127.0.0.1。解決辦法是通過Spring導出服務時設置自己的RMISocketFactory。在驗證代碼時發現自己實現的RMISocketFactory在有大量RMI請求時,會將造成系統的資源泄漏,導致請求時無法創建本地線程。

通過jconsole一看,原來在大量RMI請求時,生成了大量的RMI線程並且不會及時釋放掉,而不自定義socketfactory則沒有此問題。

公關了2天,各種嘗試,今天終於找到的了原因:其實Oracle的FAQ早有說明:

http://docs.oracle.com/javase/7/docs/technotes/guides/rmi/faq.html

A.5 Why does the Java RMI implementation create so many sockets when my application uses custom socket factories; or why are stubs (using a custom socket factory) that refer to the same remote object not equal; or why does the Java RMI implementation not reuse server-side ports when I use a custom server socket factory?

The Java RMI implementation attempts to reuse open sockets where possible for remote invocations. When a remote method is invoked on a stub that uses a custom socket factory, the Java RMI implementation will reuse an open connection (if any) as long as that socket was created by an equivalent socket factory. Since client socket factories are serialized to clients, a single client may have several distinct copies of the same logical socket factory. To ensure that the Java RMI implementation will reuse sockets created by custom socket factories, make sure your custom client socket factory classes implement the hashCode and equalsmethods appropriately. If the client socket factory does not implement these methods correctly, another ramification is that stubs (using the client socket factory) that refer to the same remote object will not be equal.

The Java RMI implementation attempts to reuse server-side ports as well. It will only do so if there is an existing server socket for the port created by an equivalent socket factory. Make sure the server socket factory class implements the hashCode and equals methods too.

If your socket factory has no instance state, a trivial implementation of the hashCode and equals methods are the following:

    public int hashCode() { return 57; }
    public boolean equals(Object o) { return this.getClass() == o.getClass(); }


實現了hashCode和equals後,問題解決,網上的例子,包括spring的文檔都沒說這個,坑爹啊,大家都沒發現這個問題?


共享下調試代碼,供後面有相同問題的人蔘考

調試代碼使用了spring2.5.5編譯調試,使用時需要將其和相應依賴的包導入classpath

wKioL1P5PlWTq_5CAAF3vxIjH0U271.jpg

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章