Calling `defineClass` on ClassLoader results in "No matching method found"

194 views Asked by At

I generated a class using ASM and now I'm trying to load this class using the ContextClassLoader:

(.defineClass classloader (str pkg "." classname) controllerclass 0 (count controllerclass))

controllerclass is the Byte-array containing the class. The exception I get is:

java.lang.IllegalArgumentException: No matching method found: defineClass for class sun.misc.Launcher$AppClassLoader, compiling:(fxml_test.clj:29:1)
Exception in thread "main" java.lang.IllegalArgumentException: No matching method found: defineClass for class sun.misc.Launcher$AppClassLoader, compiling:(fxml_test.clj:29:1)
        at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3700)
        at clojure.lang.Compiler.compile1(Compiler.java:7609)
        at clojure.lang.Compiler.compile(Compiler.java:7676)
        at clojure.lang.RT.compile(RT.java:413)
        at clojure.lang.RT.load(RT.java:458)
        at clojure.lang.RT.load(RT.java:426)
        at clojure.core$load$fn__6548.invoke(core.clj:6046)
        at clojure.core$load.invokeStatic(core.clj:6045)
        at clojure.core$load.doInvoke(core.clj:6029)
        at clojure.lang.RestFn.invoke(RestFn.java:408)
        at clojure.core$load_one.invokeStatic(core.clj:5848)
        at clojure.core$compile$fn__6553.invoke(core.clj:6056)
        at clojure.core$compile.invokeStatic(core.clj:6056)
        at clojure.core$compile.invoke(core.clj:6048)
        at user$eval246$fn__255.invoke(form-init5690492012618124781.clj:1)
        at user$eval246.invokeStatic(form-init5690492012618124781.clj:1)
        at user$eval246.invoke(form-init5690492012618124781.clj:1)
        at clojure.lang.Compiler.eval(Compiler.java:7062)
        at clojure.lang.Compiler.eval(Compiler.java:7052)
        at clojure.lang.Compiler.eval(Compiler.java:7052)
        at clojure.lang.Compiler.load(Compiler.java:7514)
        at clojure.lang.Compiler.loadFile(Compiler.java:7452)
        at clojure.main$load_script.invokeStatic(main.clj:278)
        at clojure.main$init_opt.invokeStatic(main.clj:280)
        at clojure.main$init_opt.invoke(main.clj:280)
        at clojure.main$initialize.invokeStatic(main.clj:311)
        at clojure.main$null_opt.invokeStatic(main.clj:345)
        at clojure.main$null_opt.invoke(main.clj:342)
        at clojure.main$main.invokeStatic(main.clj:424)
        at clojure.main$main.doInvoke(main.clj:387)
        at clojure.lang.RestFn.applyTo(RestFn.java:137)
        at clojure.lang.Var.applyTo(Var.java:702)
        at clojure.main.main(main.java:37)
Caused by: java.lang.IllegalArgumentException: No matching method found: defineClass for class sun.misc.Launcher$AppClassLoader
        at clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:53)
        at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:28)
        at clojurefx.controllergen$gen_fx_controller_class.invokeStatic(controllergen.clj:198)
        at clojurefx.controllergen$gen_fx_controller_class.invoke(controllergen.clj:185)
        at clojurefx.fxml$load_fxml_with_controller.invokeStatic(fxml.clj:13)
        at clojurefx.fxml$load_fxml_with_controller.invoke(fxml.clj:12)
        at clojure.lang.AFn.applyToHelper(AFn.java:156)
        at clojure.lang.AFn.applyTo(AFn.java:144)
        at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3695)
        ... 32 more

I tried adding type hints, but that had no effect. How do I tell Clojure which method exactly to use? The types definitely match the ones shown in the javadoc of Java 8.

1

There are 1 answers

1
Piotr Wilkin On

The defineClass method is not even accessible in AppClassLoader since it inherits from URLClassLoader and defineClass is private in that class.

Generally, what you want to do is you want to register the class you compiled as a classloader resource so that it can find it natively using findClass.