DevMode Launch在GWT JSNI项目中失败

时间:2014-12-03 10:22:42

标签: gwt jsni gwt-super-dev-mode dev-mode

我遇到了gwt dev模式调试的奇怪问题。

以下是我写的https://github.com/sillysachin/GWTAMChart

的JSNI包装器

这是一个相当小而简单的项目,包含大量JSNI,JavaScriptObject和JSON代码。它包含了流行的amcharts图表库。在SuperDevMode和Production中调试时,它运行良好。

但是我无法使用开发模式调试在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)

2 个答案:

答案 0 :(得分: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

您似乎遇到了叠加类型的限制 - only one JavaScriptObject subtype can implement any given interface

  

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

查看您的代码时,此限制已被破坏:AmChartJSO实现IsAmChart,但AmCoordinateChartJSO实现了扩展IsAmCoordinateChart的{​​{1}} - 因此两个JSO实施相同的界面。如果我正确理解了这个限制,你甚至不能创建一个实现接口的JSO子类。

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

IsAmChart

同样无用的例外:

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() {
    }
}

请参阅this thread on GWT's mailing list了解此问题的解决方法和一般性讨论。


自己转储生成的类文件

为了将来参考,您可以通过设置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) 系统属性(class)来转储生成的gwt.dev.classDump字段。有关详细信息,请参阅this wiki page。默认情况下,类会写入-Dgwt.dev.classDump=true文件夹(在您的情况下,它将是rewritten-classes)。这些类按包进行组织,因此查找war/rewritten-classes非常简单:JavaScriptObject$

现在,您需要做的就是反汇编它 - 我使用了Bytecode Outline plugin for Eclipse并获得了rewritten-classes/com/google/gwt/core/client/JavaScriptObject$.class的字节码。

为了找出哪些方法是重复的,我可以使用类加载器加载JavaScriptObject$.class文件并让JVM弄清楚...但我感觉很懒,所以我只是class在字节码中编辑grep并运行uniq -D以仅查看重复的条目。

答案 1 :(得分:0)

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