【问题标题】:Calling `defineClass` on ClassLoader results in "No matching method found"在 ClassLoader 上调用 `defineClass` 会导致“找不到匹配的方法”
【发布时间】:2017-11-14 13:59:45
【问题描述】:

我使用 ASM 生成了一个类,现在我尝试使用 ContextClassLoader 加载这个类:

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

controllerclass 是包含该类的字节数组。我得到的例外是:

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

我尝试添加类型提示,但没有效果。我如何告诉 Clojure 究竟使用哪种方法?这些类型肯定与 Java 8 的 javadoc 中显示的类型相匹配。

【问题讨论】:

    标签: java clojure classloader contextclassloader


    【解决方案1】:

    defineClass 方法甚至无法在 AppClassLoader 中访问,因为它继承自 URLClassLoader 并且 defineClass 在该类中是私有的。

    通常,您要做的是将您编译的类注册为类加载器资源,以便它可以使用findClass 在本机找到它。

    【讨论】:

    • 你可能是对的,这是一个可访问性问题,但不是细节问题。基础ClassLoader 提供了三个protected 版本的defineClass()(而SecureClassLoader 提供了另外两个); OP 似乎正在尝试使用其中之一。除了子类或同一包中的其他地方之外,Java 代码通常无法访问它们,但我不确定它们是否可以通过 OP 使用的 Clojure / ASM 技术使用。
    猜你喜欢
    • 1970-01-01
    • 2011-08-13
    • 2011-12-06
    • 1970-01-01
    • 2019-01-20
    • 1970-01-01
    • 2020-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多