Hey all, Once again I'm lending my hand at trying to get some clojure code working under OSGi, and once again hitting issues with the good ole class loader. I have a simple OSGi bundle project which embeds clojure.jar, and contains a single source file:
(ns com.theoryinpractise.activator.osgi.components (:import (org.osgi.framework BundleActivator))) (deftype MyActivator [] BundleActivator (start [this context] (println "Hello from service")) (stop [this context] (println "stopping"))) In my OSGi metadata I have `com.theoryinpractise.activator.osgi.components.MyActivator` listed as the `Bundle-Activator` for the bundle, and when I load it I get the following exception: Caused by: java.lang.ExceptionInInitializerError at com.theoryinpractise.activator.osgi.components.MyActivator.<clinit>(components.clj:4) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:526) at java.lang.Class.newInstance(Class.java:374) at org.apache.felix.framework.Felix.createBundleActivator(Felix.java:4336) at org.apache.felix.framework.Felix.activateBundle(Felix.java:2141) ... 32 more Caused by: java.io.FileNotFoundException: Could not locate clojure/core__init.class or clojure/core.clj on classpath: at clojure.lang.RT.load(RT.java:443) at clojure.lang.RT.load(RT.java:411) at clojure.lang.RT.doInit(RT.java:447) at clojure.lang.RT.<clinit>(RT.java:329) ... 40 more java.lang.ExceptionInInitializerError When I look at the decompiled class ( using JD-GUI ) I see there's a static initialiser pulling in the `println` function: public final class MyActivator implements BundleActivator, IType { public static final Var const__0 = (Var)RT.var("clojure.core", "println"); … Tracing this down into `RT.baseLoader()`: static public ClassLoader baseLoader(){ if(Compiler.LOADER.isBound()) return (ClassLoader) Compiler.LOADER.deref(); else if(booleanCast(USE_CONTEXT_CLASSLOADER.deref())) return Thread.currentThread().getContextClassLoader(); return Compiler.class.getClassLoader(); } I find that `Compiler.LOADER.isBound()` is false, and `booleanCast(USE_CONTEXT_CLASSLOADER.deref())` is true, which leads to using the class loader for the OSGi runtime and *not* the class loader that happens to actually know anything about Clojure, which would be the OSGi Bundle classloader for my package. Does anyone know of a way around this? Or will I need to give up on trying to use pure-clojure here and use Java for my activator, and call `Compiler.LOADER.set(myclassloader)` and then do some `RT.*` love? Cheers, Mark
signature.asc
Description: OpenPGP digital signature