Get original exported object back?

It just sunk in that when I pass out my Project as an IProject, its actually going out as a Proxy. So when I get back in another interface IProject I cant then do this;

void remoteCall(IProject project){

Project proj = (Project) project;

}

Is there any utility already in RMI that will get my my original object back? Or should I get it back myself? I thought toStub would do that, but it really did not do anything..

Thanks!

[547 byte] By [_dnoyeBa] at [2007-11-26 17:07:36]
# 1
What are you reaally trying to do?
bschauwejavaa at 2007-7-8 23:35:25 > top of Java-index,Core,Core APIs...
# 2

Well since you asked kindly...

I put objects inside of objects.

interface IProject {

void addArchitecture(IArchitecture arch);

}

Now, IProject and IArchitecture are both Remote. So when The method is called I was trying to do like so

Project implements IProject {

void addArchitecture(IArchitecture architecture){

Architecture arch = (Architecture)architecture;//ClassCastException

archList.add(arch.getInnerArch());

}

}

Thats what I am really trying to do.

_dnoyeBa at 2007-7-8 23:35:25 > top of Java-index,Core,Core APIs...
# 3
Why do you need the original object instead of the interface?
ejpa at 2007-7-8 23:35:25 > top of Java-index,Core,Core APIs...
# 4

Thinking about this a bit, one way I came up with is as follows:

Assuming that architectures exist in some pool on the server, provide each of them with an ID, and make the architectures retrievable from the pool by ID.

Give the architecture interface a method that returns the architecture ID.

Let the project ask for the ID, then retrieve the architecture from the pool.

bschauwejavaa at 2007-7-8 23:35:25 > top of Java-index,Core,Core APIs...
# 5

> Why do you need the original object instead of the

> interface?

public interface IProject {

public void addArchitecture(IArchitecture arch);

}

public interface IArchitecture {

//stuff

}

class Architecture implements IArchitecture {

//IArchitecture methods

//internal methods

DBArchitecture getInnerArch(){

return hibernateObject;

}

}

class Project implements IProject {

private List archList;

void addArchitecture(IArchitecture architecture){

Architecture arch = (Architecture)architecture;//ClassCastException

archList.add(arch.getInnerArch());

}

}

I need this inside the server because as you see above there are methods on the original object that are not present on the remote interface. There is a heirachical relationship between my objects and one can be added to another. I can not add a proxy interface to another proxy interface. That does not work. So I need to de-proxy and get the internal object, then do the adding.

_dnoyeBa at 2007-7-8 23:35:25 > top of Java-index,Core,Core APIs...
# 6

> Thinking about this a bit, one way I came up with is

> as follows:

>

> Assuming that architectures exist in some pool on the

> server, provide each of them with an ID, and make the

> architectures retrievable from the pool by ID.

>

They do have an ID. Currently I have them in a pool of my creating. But I was wondering if RMI did not already have them in a pool somewhere. If that was the case then I would use RMI's pool and not have redundant pools.

> Give the architecture interface a method that returns

> the architecture ID.

No need because I still need the internal object for the adding.

>

> Let the project ask for the ID, then retrieve the

> architecture from the pool.

The id is available to the project.

_dnoyeBa at 2007-7-8 23:35:25 > top of Java-index,Core,Core APIs...
# 7

Well this has been a learning experience. My pool did not work as expected. I only found out today.

I have been calling

exportObject(myobject);//or whtever its called

Then I proceed to put my object into a weak cache for purpose of multiton. Unfortunately, RMI holds onto the object returned from the exportObject call (I think since I implemented unreferenced but its not been called), and it does not hold onto the object passed into that call. So I have been happily getting my objects out the 'cache' if available and recreating if not. This has caused a lot of recreation and I figured out that its because my objects are reclaimed very quickly because there is no hard reference to them anywhere...

But how is it possible for the exported object to exist, but the original object that it is supposedly forwarding its calls to, not exist?

So the question is, what references, if any, are held to exported objects that implement Remote interface? Note: the client still...Hmm. No actually I put off that optimization until later. So the clients do re-get the remote object on each invocation and only hold and id. So that means nobody is holding references to my exported objects. I thought the DGC ran every 10 minutes? I don't know what the deal is but this is what I do know.

My Remote object implements Unreferenced. I hold a weak reference to my remote object. The weak reference is cleared, but unreference is never called.

What gives?

_dnoyeBa at 2007-7-8 23:35:25 > top of Java-index,Core,Core APIs...
# 8

Hehe, thats why I always give up and post to the forums. About 1/2 the time when I post I find the problem. My objects are being unreferenced and dumped from my 'cache' immediately after export. So they are good for one use, then discarded. Ouch.

I think though I only have to optimize the client and once I do that the DGC will hold my objects around longer. I am assuming this means the DGC runs very frequently and not every 10 minutes...

_dnoyeBa at 2007-7-8 23:35:25 > top of Java-index,Core,Core APIs...
# 9

> Unfortunately, RMI holds onto

> the object returned from the exportObject call (I

> think since I implemented unreferenced but its not

> been called), and it does not hold onto the object

> passed into that call.

It has a strong reference to the stub and a weak reference to the remote object.

> My Remote object implements Unreferenced. I hold a

> weak reference to my remote object. The weak

> reference is cleared, but unreference is never

> called.

This just means that DGC has never found the object to be releasable. This is completely separate from local GC.

DGC runs every ten minutes or so but this should start immediately a client receives a stub, i.e. not ten minutes later. This acquires a DGC lease, then it tries to renew the lease in the middle of the 10-minute expiry time.

ejpa at 2007-7-8 23:35:25 > top of Java-index,Core,Core APIs...
# 10

> > Unfortunately, RMI holds onto

> > the object returned from the exportObject call (I

> > think since I implemented unreferenced but its not

> > been called), and it does not hold onto the object

> > passed into that call.

>

> It has a strong reference to the stub and a weak

> reference to the remote object.

>

Indeed. What I said above is sort of backwards.

> > My Remote object implements Unreferenced. I hold

> a

> > weak reference to my remote object. The weak

> > reference is cleared, but unreference is never

> > called.

>

> This just means that DGC has never found the object

> to be releasable. This is completely separate from

> local GC.

>

The local GC can't reclaim an object that the DGC has yet to release.

> DGC runs every ten minutes or so but this should

> start immediately a client receives a stub, i.e. not

> ten minutes later. This acquires a DGC lease, then it

> tries to renew the lease in the middle of the

> 10-minute expiry time.

Thats what I was expecting. But its kind of a misnomer. The DGC is always running. Its only checking for expiration every 10 minutes. In the meantime, any objects that the client explicitly says it does not need, the DGC may reclaim at any time.

In the end I am using a WeakHashMap to hold my remote objects. Its my first time finding a use for that weird map...

_dnoyeBa at 2007-7-8 23:35:25 > top of Java-index,Core,Core APIs...
# 11

> > DGC runs every ten minutes or so but this should

> > start immediately a client receives a stub, i.e.

> not

> > ten minutes later. This acquires a DGC lease, then

> it

> > tries to renew the lease in the middle of the

> > 10-minute expiry time.

>

> Thats what I was expecting. But its kind of a

> misnomer. The DGC is always running. Its only

> checking for expiration every 10 minutes. In the

> meantime, any objects that the client explicitly says

> it does not need, the DGC may reclaim at any time.

Sorry, I was unclear. There are two parts, the DGC server and the DGC clients. The DGC server is running all the time looking for expired leases. DGC at the client runs to keep those leases alive every 10 minutes, which should start as soon as the client unmarshalls the stub. See http://java.sun.com/j2se/1.5.0/docs/guide/rmi/spec/rmi-arch4.html for details.

ejpa at 2007-7-8 23:35:25 > top of Java-index,Core,Core APIs...
# 12

My only point is that its not all about expired leases. The DGC will reclaim objects that do not have expired leases if the client states it does not need them anymore.

My first impression was that objects would not be reclaimed except on a 10 minute cycle. But this is not the case. dropped connections are cleaned up on 10 minute cycle.

_dnoyeBa at 2007-7-8 23:35:25 > top of Java-index,Core,Core APIs...