3

我在 gwt 开发模式调试中遇到了一个奇怪的问题。

以下是我正在编写的 JSNI 包装器https://github.com/sillysachin/GWTAMChart

这是一个相当小而简单的项目,包含大量 JSNI、JavaScriptObject 和 JSON 代码。它包含了流行的 amcharts 图表库。在 SuperDevMode 和生产环境中调试时效果很好。

但是,我无法使用开发模式调试在 Internet Explorer 中调试该项目。

java.lang.ClassFormatError:类文件 com/google/gwt/core/client/JavaScriptObject$ 中的方法名称和签名重复

抛出的主要异常没有帮助我确定代码的哪一部分正在破坏!!!!!!

java.lang.ClassFormatError: Duplicate method name&signature in class file com/google/gwt/core/client/JavaScriptObject$
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:643)
    at com.google.gwt.dev.shell.CompilingClassLoader.findClass(CompilingClassLoader.java:1142)
    at com.google.gwt.dev.shell.CompilingClassLoader.loadClass(CompilingClassLoader.java:1215)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:270)
    at com.google.gwt.dev.shell.JsValueGlue.set(JsValueGlue.java:220)
    at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:130)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:589)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNativeVoid(ModuleSpace.java:315)
    at com.google.gwt.dev.shell.ModuleSpace.onLoad(ModuleSpace.java:359)
    at com.google.gwt.dev.shell.OophmSessionHandler.loadModule(OophmSessionHandler.java:200)
    at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:530)
    at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:368)
    at java.lang.Thread.run(Thread.java:745)
4

2 回答 2

1

有问题的类正在AmChartJSO实现IsAmChart接口 - 所有方法都在JavaScriptObject$. 来自字节码的片段:

public final synthetic com_amcharts_api_IsAmChart_setVersion(Ljava/lang/String;)V
  ALOAD 0
  ALOAD 1
  INVOKESTATIC com/amcharts/jso/AmChartJSO$.setVersion$ (Lcom/amcharts/jso/AmChartJSO;Ljava/lang/String;)V
  RETURN
  MAXSTACK = 2
  MAXLOCALS = 2

// access flags 0x1011
public final synthetic com_amcharts_api_IsAmChart_setVersion(Ljava/lang/String;)V
  ALOAD 0
  ALOAD 1
  INVOKESTATIC com/amcharts/jso/AmChartJSO$.setVersion$ (Lcom/amcharts/jso/AmChartJSO;Ljava/lang/String;)V
  RETURN
  MAXSTACK = 2
  MAXLOCALS = 2

您似乎遇到了覆盖类型的限制——只有一个 JavaScriptObject 子类型可以实现任何给定的接口

实际上,这意味着只有一种 JavaScriptObject 类型可以实现任何给定的接口,但任意数量的非 JavaScriptObject 类型也可以实现该接口。

查看您的代码,此限制已被打破:AmChartJSOimplements IsAmChart,但AmCoordinateChartJSOimplements IsAmCoordinateChartwhich extends IsAmChart- 因此两个 JSO 实现了相同的接口。如果我正确理解了这个限制,你甚至不能子类化实现接口的 JSO。

我做了一个快速测试,这段代码也失败了:

public class Test extends JavaScriptObject implements TakesValue<String> {
    protected Test() {
    }

    @Override
    public final void setValue(String value) {
    }

    @Override
    public final String getValue() {
        return null;
    }
}

public class Test2 extends Test {
    protected Test2() {
    }
}

有一个同样无用的例外:

java.lang.NullPointerException: null
    at com.google.gwt.dev.shell.CompilingClassLoader$MySingleJsoImplData.findOverloadUsingErasure(CompilingClassLoader.java:703)
    at com.google.gwt.dev.shell.CompilingClassLoader$MySingleJsoImplData.<init>(CompilingClassLoader.java:593)
    at com.google.gwt.dev.shell.CompilingClassLoader.<init>(CompilingClassLoader.java:980)
    at com.google.gwt.dev.shell.ShellModuleSpaceHost.onModuleReady(ShellModuleSpaceHost.java:137)
    at com.google.gwt.dev.shell.ModuleSpace.onLoad(ModuleSpace.java:340)
    at com.google.gwt.dev.shell.OophmSessionHandler.loadModule(OophmSessionHandler.java:200)
    at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:526)
    at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:364)
    at java.lang.Thread.run(Thread.java:745)

在 GWT 的邮件列表中查看此线程以了解解决方法和对此问题的一般讨论。


自己转储生成的类文件

class为了将来参考,您可以通过设置gwt.dev.classDump系统属性 ( -Dgwt.dev.classDump=true)来转储生成的文件。有关更多信息,请参阅此 wiki 页面。默认情况下,类被写入rewritten-classes文件夹(在您的情况下,它将是war/rewritten-classes)。这些类是按包组织的,所以JavaScriptObject$很容易找到:rewritten-classes/com/google/gwt/core/client/JavaScriptObject$.class.

现在,你需要做的就是反汇编它——我已经使用了Eclipse 的 Bytecode Outline 插件并获得了JavaScriptObject$.class.

要找出重复的方法,我可以class使用类加载器加载文件并让 JVM 找出来......但我觉得很懒所以我只是在字节码中grep编辑并运行以仅查看重复的条目.public final syntheticuniq -D

于 2014-12-07T19:04:33.743 回答
0

使用 JSNI 时,这会在开发模式下发生。由于超级开发模式直接在浏览器中使用纯java脚本进行调试,因此没有严格的类型转换,不会产生错误。在开发模式下,Java 代码运行并且由于严格的类型转换,您将获得类格式异常。没有任何用处。highcharts也有同样的问题。如果它在生产和超级开发模式下运行良好,那么你不应该担心它。希望能帮助到你。

于 2014-12-04T09:19:16.793 回答