简体   繁体   中英

DevMode Launch fails in GWT JSNI project

I have run into a weird issue with gwt dev mode debugging.

Following is a JSNI wrapper I am writing https://github.com/sillysachin/GWTAMChart

It is fairly small and simple project with lots of JSNI, JavaScriptObject and JSON code. It wraps over popular amcharts charting library. It works well when debugged in SuperDevMode and in Production.

However I am not able to debug the project in Internet Explorer with Dev Mode Debugging.

java.lang.ClassFormatError: Duplicate method name&signature in class file com/google/gwt/core/client/JavaScriptObject$

The main exception thrown is not helping me figure which part of code is breaking !!!!!

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)

The problematic class is AmChartJSO implementing the IsAmChart interface - all the methods are declared twice in JavaScriptObject$ . Snippet from the bytecode:

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

It seems you've run into a limitation of overlay types - only one JavaScriptObject subtype can implement any given interface :

Practically speaking, this means that only one JavaScriptObject type may implement any given interface, but any number of non-JavaScriptObject types may also implement that interface.

Looking at your code, this restriction is broken: AmChartJSO implements IsAmChart , but AmCoordinateChartJSO implements IsAmCoordinateChart which extends IsAmChart - and thus two JSOs implement the same interface. If I understand this restriction correctly, you can't even subclass a JSO that implements an interface.

I've done a quick test and this code fails too:

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

With a similarly useless exception:

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)

Please see this thread on GWT's mailing list for workarounds and general discussion of this problem.


To dump the generated class files yourself

For future reference, you can dump the generated class filed by setting the gwt.dev.classDump system property ( -Dgwt.dev.classDump=true ). See this wiki page for more information. By default the classes are written to the rewritten-classes folder (in your case it will be war/rewritten-classes ). The classes are organized by packages, so finding JavaScriptObject$ is easy: rewritten-classes/com/google/gwt/core/client/JavaScriptObject$.class .

Now, all you need to do is disassemble it - I've used the Bytecode Outline plugin for Eclipse and got the bytecode of JavaScriptObject$.class .

To find out which methods were duplicated, I could just load the class file with a classloader and let the JVM figure it out... But I was feeling lazy so I've just grep ed for public final synthetic in the bytecode and run uniq -D to see only the duplicated entries.

This happens in dev mode when using JSNI. Since super dev mode directly debugs in browser with pure java script, there is no strict type casting and produce no errors. Where as in dev mode the java code runs and due to strict type casting you will get class format exception. There is no avail. Same problem with highcharts as well. If it works well in production and super dev mode then you should not worry about it. Hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM