On Thursday, March 3, 2011 11:46:03 AM UTC+1, Jules wrote:
>
>
>
> Thanks, Alessio, 
>
> I did know this, but it is a welcome addition to the thread. 
>

Ok. Classloaders are a tricky matter and many people don't have clear ideas 
about them - sorry for assuming you were one of those people :)
 

> I reread my last posting and it was a bit confused - I've done a 
> little research in the Compiler class and can now clarify what I think 
> is happening. 
>
> Clojure 1.3.0-alpha4 
> user=> (type (fn [])) 
> user$eval1$fn__2 
> user=> 
>
> Here I have created a new function and asked it for its class. Clojure 
> has emitted bytecode on the fly to implement this and packed this into 
> a Java Class. A Class has a name unique - as you pointed out - within 
> its ClassLoader, so to avoid name collisions, Clojure attempts to 
> create a unique name for the class. This is composed, amongst other 
> things from its namespace and RT.nextID() (I'm assuming RT = RunTime). 
>
> RT.nextID seems to start at 0 and allocate ids sequentially - lets 
> create another fn : 
>
> user=> (type (fn [])) 
> user$eval5$fn__6 
> user=> 
>
> I suspect that the gap between 2 and 6 is due to other processes going 
> on behind the scenes which require ids, rather than some intentional 
> design - but haven't checked. 
>
> This all works fine in a single JVM - no two functions will end up 
> creating types with the same name - however if I take the class for a 
> function from [a ClassLoader in] one clojure runtime and copy it 
> across to another clojure runtime that has already allocated this 
> classes id to another [in the receiving ClassLoader] then I would see 
> a collision. 
>
> I think that this is what is happening above. I am serialising an 
> object in one jvm, putting it into a message and sending the message 
> to another jvm. Upon receipt I attempt to deserialise the object 
> contained in the message. This involves looking up its class by name 
> [within the scope of a ClassLoader] - but the name has already been 
> allocated to a local class [within the same ClassLoader] which is 
> mistakenly then used to try to deserialise the object. The object's 
> data is not presented in the format that the local class expects for 
> one of its own instances - hence the Exception in my posting above. 
>
> This is currently only theory. 
>

Makes sense.
 

> I think that the easiest way to fix it is to use not just a jvm-local 
> uid as part of the class name, but also an id which uniquely 
> identifies this jvm amongst all the jvms involved in my cluster. It 
> looks like not too many classes make use of RT.nextID(), so I think my 
> next move will be to add an e.g. RT.jvmID and use this in conjunction 
> with RT.nextID(). If this resolves my problem then there is a good 
> chance that my supposition was correct - otherwise it is back to the 
> drawing board. 
>

I think a better option is to make sure that the classloader you use for 
deserializing is completely separated from the classloader Clojure uses to 
load compiled functions. Then, no possibility of collision exists, 
regardless of how you generate class names.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to