Thanks, that was insightful. To recap, subclassloader is a
optimization to reduce the startup time of launching a new clojure
instance from leiningen. In addition, I learned that computing the
classpath was conducted in clojure code. I see now that the bash
script is just a bootstrapping tool to get an instance of clojure
running. This means that we have the full power of clojure at our
disposal to compute the desired classpath. Many people make the more
complex compute classpath feature request but may not realize the
reasonable tractability of writing such a plugin.

On another note, I'm currently concerned with utilizing a global
configuration of leiningen (e.g. installing plugins and define
additional repositories globally). My current idea is to create a git
fork/branch to manage personal configuration files within the checkout
folder and then implement a bootstrapping script to facilitate
automating the deployment of alternative branches of leiningen.

Brent

Alex Osborne wrote:
> Brent Millare <brent.mill...@gmail.com> writes:
>
> > Can someone please elaborate on this subclassloader process? Although
> > the design for leiningen is architecturally simple and understandable
> > and thus easy to extend, I'm still quite unfamiliar with the "java
> > way". I believe a little documentation on this aspect can make a
> > significant improvement in allowing contributions to leiningen.
>
> Given I implemented the initial support for it, I'll give it a go.  In
> earlier versions of Leiningen you weren't able to compile code against a
> different version of Clojure to the one that Lein was running on top
> of, as you could only have one or the other in the classpath.  One way to
> get around this is to fork off a new java process and run the compile in
> a separate JVM.  Unfortunately we'd then be incurring the JVM's startup
> overhead twice (and lein is already annoyingly slow to start).  Wouldn't
> it be nice if we could just run the compile in the original JVM but
> isolated in a container somehow?
>
> Well we can actually do this because the JVM supports custom
> classloaders.  A classloader is an object that when given a classname,
> locates the appropriate class files (in jars, classpath etc) and loads it
> into memory.  There's a default builtin classloader which searches the
> classpath you supply on the command-line. Custom classloaders can be
> used for a number of things, for example loading jars over the network
> or out of a new archive format.  They also play a strong role in the
> JVM's security module (for sandboxing etc).  When a class is loaded
> (manually) into a custom classloader, any classes it in turn
> tries to load (by normal means) are also loaded via that same
> classloader.
>
> So basically what Lein does is creates a new classloader (it actually
> reuses Apache Ant's implementation) with a different classpath which
> points to the version of clojure and other libraries that you want to
> compile against.
>
> Take a look at the eval-in-project function in leiningen/compile.clj.
> You pass in a form to be evaluated as an argument.  It's converted to a
> string and then clojure.main is invoked with the '-e' argument to
> evaluate the string 'inside' the new classloader.  The reason its done
> this way is so that its easy to fall back to forking and also because
> objects in the new classloader aren't compatible with those in the
> original (as they're potentially different versions of Clojure).
>
> You can see that it doesn't work perfectly for all cases, so for example
> if you're using native libs or OS X it'll fork instead.  (OS X injects
> some GUI stuff into the classpath of all the apps it runs, so anything
> using using Swing or AWT doesn't work properly in the new classloader).
>
> You may have wondered how Java servlet containers like Jetty and Tomcat
> are able to load different versions of the same class into the same JVM
> without them conflicting.  As I understand it they use basically the
> same mechanism.
>
> Hope that helps.  If you're having trouble following the classloader
> stuff just think of the eval-in-project function as starting a new
> "virtual" JVM with a different classpath and evaling some code in it.
> Its really not all that complex, its just the terminology makes it sound
> somewhat arcane.
>
> Alex

-- 
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

To unsubscribe from this group, send email to 
clojure+unsubscribegooglegroups.com or reply to this email with the words 
"REMOVE ME" as the subject.

Reply via email to