Hi Roger,
Thank you for reviewing. File bug:
https://bugs.openjdk.java.net/browse/JDK-8170728
-Hamlin
On 2016/12/5 22:31, Roger Riggs wrote:
Hi Hamlin,
The changeset looks fine (to use /othervm).
Please file a new issue for your finding about createRegistry(0); I
agree it is likely a product issue.
Thanks, Roger
On 12/5/2016 3:12 AM, Hamlin Li wrote:
Would you please review the below patch?
bug: https://bugs.openjdk.java.net/browse/JDK-8170669
webrev: http://cr.openjdk.java.net/~mli/8170669/webrev.00/
Root Cause:
2 tests impact each other.
(test/com/sun/jndi/rmi/registry/RegistryContext/ContextWithNullProperties.java,
UnbindIdempotent.java)
Solution:
adding othervm should resolve the issue.
Thank you
-Hamlin
p.s. Besides of the test issue talked above, I think there is some
defect in RMI API, below is the analysis.
Root Cause:
when calling LocateRegistry.createRegistry(port), it will check if
the ObjectTable contains the same ObjectEndPoint, if it contains,
"java.rmi.server.ExportException: internal error: ObjID already in
use" is thrown in ObjectTable.java. 2 ObjectEndPoint objects are
considered the same if both have the same id and same tranport
instance. For 2 calls of LocateRegistry.createRegistry(0), they have
the same id(ObjID.REGISTRY_ID) and same endpoint & transport
instance, so they are considered the same and exception is thrown.
================= more detailed explanation =================
Although in
LocateRegistry.createRegistry(0)->...->TCPTransport->exportObject(target)->TCPTransport.listen()->TCPEndpoint.setDefaultPort(...),
it will add new endpoint instance for port 0 with a specific port
number(for example, it's 9999) in localEndpoints, but it still keeps
endpoint instance for port 0 in localEndpoints, and both endpoints(0,
9999) are mapped to the same epList which includes one item with port
number as 9999. the transport member of previous 2 endpoint
instances(0, 9999) is indeed built on port 9999, this transport
listening on port 9999 is used as part of key(other part is object
id) to insert into ObjectTable. so when
LocateRegistry.createRegistry(0) is called second time,
LocateRegistry.createRegistry(0)->...->TCPEndpoint.getLocalEndpoint(0,
...) will get the previous transport instance(listening on 9999), so
finally, in
LocateRegistry.createRegistry(0)->...->ObjectTable.putTarget(target),
in line 183 of ObjectTable.java, objTable.containsKey(oe) will return
true, then exception is thrown.
================= conclusion =================
I think this is a RMI product issue, because below code runs
successfully,
Registry registry1 = LocateRegistry.createRegistry(60003);
Registry registry2 = LocateRegistry.createRegistry(60004);
but below code will throw exception,
Registry registry1 = LocateRegistry.createRegistry(0);
Registry registry2 = LocateRegistry.createRegistry(0);