Hi, This sounds very interesting and useful.
Is the source code available somewhere? Or a more detailed description? Thanks On Fri, Mar 4, 2011 at 1:48 AM, Jules <jules.gosn...@gmail.com> wrote: > > So, > > Just a quick update. > > I gave the client-side ClassLoader encapsulation idea some more > thought and rejeted it (sorry) for the reasons that : > > - I've lived through J2EE ClassLoader hell and don't want to repeat > the experience > > - I'm looking towards an architecture where I can define new types on > any node of my Clojure data-grid and have them accessible in any other > node. This might be done by keeping my class-name:bytecode table in a > clustered cache and inserting a single ClusteredClassLoader (NYI) into > the client's ClassLoader hierarchy. Each client would be able to mix > classes from multiple server JVMs without having to be concerned about > keeping them all segregated. > > So, I introduced the concept of a per-jvm id and hacked it into RT, > Compiler and LispReader. There were not too many places that needed to > be changed. > > The result is, I can now create a type in one jvm, create an instance > of the type, serialise it, ship the bytes to another jvm and > deserialise it, at which point the instance's class is pulled from the > original jvm. No more nasty exceptions because of name collisions etc. > > I have plumbed this infrastructure in underneath my app and, with the > exception of some unrelated bugs that I am chasing down, everything > seems to work beautifully :-) > > There are some limitations with this technique that I haven't looked > into too deeply yet - the most obvious one is that whilst remote types > can be made available within a local jvm, this is only at the java > level, so extra things that defrecord might do for you like intern the > classname as a symbol in your current namespace are not being done - > which, I can currently live with, but I can see this being a tripping > point to a completely transparent solution. > > For me, this is a great leap forward as I have found each Clojure JVM > an island until I got this working, but now I should be able to build > a distributed app in Clojure without having to sacrifice Clojure's > dynamicity in the process - I can have my cake and eat it :-) > > I'm going to play with it for a few days, iron out all my other issues > and investigate exactly what I have achieved, then I will post back a > proper description in case anyone else is trying to build distributed > Clojure apps in a similar manner. > > cheers > > > Jules > > On Mar 3, 2:30 pm, Jules <jules.gosn...@gmail.com> wrote: >> On Mar 3, 1:22 pm, Alessio Stalla <alessiosta...@gmail.com> wrote: >> >> >> >> >> >> > 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 :) >> >> np :-) >> >> > > 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.- Hide quoted text - >> >> > - Show quoted text - >> >> That's an interesting idea, that I haven't really pursued, I think, >> OTOH, because client-side, I think that I want to be able to mix >> objects that herald from both local and remote jvms... - but this is >> just a gut feeling, I haven't really looked for any concrete usecases >> in any detail, so I'll give your suggestion consideration and see >> whether it would fit the bill. >> >> Using your approach would also be a good way of checking that my >> assumption about the name collision was correct, so I may see if I can >> set up my code to use a different ClassLoader in which to deserialise >> to see if that solves my problem. >> >> Thanks for this idea, it may help me a lot :-) >> >> Jules- Hide quoted text - >> >> - Show quoted text - > > -- > 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 -- 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