konsoletyper / teavm-flavour

Framework for writing client-side applications using TeaVM
Apache License 2.0
110 stars 19 forks source link

0.6 RC: Absent Code Attribute compile-time error for empty methods and interfaces #31

Closed PokingUrsa closed 5 years ago

PokingUrsa commented 5 years ago

I'm converting a large Flavour project to work with 0.6 RC.

A class that used to work with earlier 0.6 builds is now failing with this error:

Caused by: java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file com/[...]

It turns out this is from an empty method. Once removed, that error went away. It would be great if Flavour didn't break in this case, or if the error message said "this may be caused by an empty method".

konsoletyper commented 5 years ago

Can you provide more info? What Java version are you using? Can you post full stack trace? Can you narrow-down problem and post a self-contained project to reproduce it?

PokingUrsa commented 5 years ago

Java 8.

Here's a stack trace for an interface that is causing this


[ERROR] Error calling proxy method org.teavm.flavour.templates.Templates.create(Lorg/teavm/metaprogramming/ReflectClass;Lorg/teavm/metaprogramming/Value;)V: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.teavm.metaprogramming.impl.UsageGenerator.emitPermutation(UsageGenerator.java:159)
    at org.teavm.metaprogramming.impl.UsageGenerator.lambda$installProxyEmitter$0(UsageGenerator.java:84)
    at org.teavm.dependency.DependencyAnalyzer.schedulePropagation(DependencyAnalyzer.java:323)
    at org.teavm.dependency.DependencyAnalyzer.schedulePropagation(DependencyAnalyzer.java:380)
    at org.teavm.dependency.DependencyNode.scheduleMultipleTypes(DependencyNode.java:215)
    at org.teavm.dependency.Transition.mergeDomains(Transition.java:69)
    at org.teavm.dependency.Transition.propagate(Transition.java:49)
    at org.teavm.dependency.Transition.consume(Transition.java:39)
    at org.teavm.dependency.DependencyAnalyzer.schedulePropagation(DependencyAnalyzer.java:338)
    at org.teavm.dependency.DependencyNode.scheduleSingleType(DependencyNode.java:90)
    at org.teavm.dependency.DependencyNode.propagate(DependencyNode.java:68)
    at org.teavm.dependency.DependencyGraphBuilder$1.lambda$invokeGetClass$1(DependencyGraphBuilder.java:394)
    at org.teavm.dependency.DependencyAnalyzer.lambda$schedulePropagation$4(DependencyAnalyzer.java:393)
    at org.teavm.dependency.DependencyAnalyzer.processQueue(DependencyAnalyzer.java:660)
    at org.teavm.dependency.DependencyAnalyzer.processDependencies(DependencyAnalyzer.java:697)
    at org.teavm.vm.TeaVM.build(TeaVM.java:376)
    at org.teavm.tooling.TeaVMTool.generate(TeaVMTool.java:413)
    at org.teavm.tooling.builder.InProcessBuildStrategy.build(InProcessBuildStrategy.java:247)
    at org.teavm.maven.TeaVMCompileMojo.executeWithBuilder(TeaVMCompileMojo.java:289)
    at org.teavm.maven.TeaVMCompileMojo.execute(TeaVMCompileMojo.java:238)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:154)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:146)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.builder.multithreaded.MultiThreadedBuilder$1.call(MultiThreadedBuilder.java:200)
    at org.apache.maven.lifecycle.internal.builder.multithreaded.MultiThreadedBuilder$1.call(MultiThreadedBuilder.java:196)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file com.[proprietary classname removed]
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:411)
    at org.teavm.metaprogramming.impl.MetaprogrammingClassLoader.loadClass(MetaprogrammingClassLoader.java:43)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at org.teavm.flavour.expr.type.meta.ClassPathClassDescriberRepository.describe(ClassPathClassDescriberRepository.java:72)
    at org.teavm.flavour.templates.parsing.Parser.parse(Parser.java:123)
    at org.teavm.flavour.templates.emitting.TemplatingProxyGenerator.parseForModel(TemplatingProxyGenerator.java:73)
    at org.teavm.flavour.templates.emitting.TemplatingProxyGenerator.generate(TemplatingProxyGenerator.java:43)
    at org.teavm.flavour.templates.Templates.create(Templates.java:61)
    ... 37 more

    at org.teavm.flavour.templates.Templates.create
    at org.teavm.flavour.templates.Templates.create(Templates.java:55)
    at org.teavm.flavour.templates.Templates.bind(Templates.java:41)
    at org.teavm.flavour.widgets.ApplicationTemplate.bind(ApplicationTemplate.java:42)
    at org.teavm.flavour.widgets.ApplicationTemplate.bind(ApplicationTemplate.java:46)
    at com.[proprietary classname removed](Client.java:48)
`
konsoletyper commented 5 years ago

I have no idea how to debug this problem and what's causing it. It does not look like TeaVM issue. TeaVM just calls standard Java API which produces error somewhere deep inside. MetaprogrammingClassLoader performs instrumentation of classes and this might be causing something like this in case of broken instrumentation. However, in case of your class it reports exception from line 43, which is simply:

return super.loadClass(name, resolve);

so no instrumentation performed.

Now you have following options to try to fix this issue:

  1. Check the corresponding class file. There's javap utility which show content of class file. Also you may try asm verifier.
  2. Send me the class file directly. We can sign NDA or something like this. You can even give me whole jar files (no sources required) so that I could reproduce the issue myself.
PokingUrsa commented 5 years ago

Thanks for the quick reply. I will examine the interface with javap and see what I can find. If I can't figure it out I'll check with our management and lawyers about option 2.

In case it helps, the same project builds fine (no errors) with TeaVM 0.6.0-dev-674 and Flavour 0.2.0-dev-52

konsoletyper commented 5 years ago

Option 3: you narrow down problem, write a tiny project that reproduces the issue with no proprietary component and safely publish it here.

PokingUrsa commented 5 years ago

You were right, there was something wrong with some lingering class files. I had been rebuilding the UI modules and their dependencies (-pl/-am), which should have been enough. However, a full rebuild of all modules seems to have fixed it.

I have 2 remaining build errors related to JSON de/serializaion, I'll create a separate issue for that.