Skip to content

Use of @Delegate causing references to classes from eclipse host jvm in emitted class file #1436

@ssadedin

Description

@ssadedin

I have set up Eclipse JDT + groovy-eclipse with JDK8 as the target JDK, which is set in my project as the target compiler level (with the --release flag selected in compiler settings). There is no JDK12 or later configured as a JDK for JDT to use.

image

However when I use the @Delegate annotation on a String field, the class file written by groovy-eclipse contains references to java.lang.constant.Constable from JDK17. JDK17 is the host JRE of the eclipse installation (bundled with Eclipse). It seems like in implementing the Delegate annotation, groovy-eclipse is introspecting the host VM rather than the target VM configured in the compiler settings.

I have created an example project here:

https://gitlab.com/ssadedin/groovy-eclipse-delegate-bug

It has only two classes, the key one in Foo.groovy which defines the Foo class as

class Foo {
    @Delegate
    String bar
}

Once the @Delegate annotation is added, attempting to run the main class causes this exception:

Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: java/lang/constant/Constable
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:757)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:473)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:419)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:352)
	at java.lang.Class.getDeclaredMethods0(Native Method)
	at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
	at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
	at java.lang.Class.getMethod0(Class.java:3018)
	at java.lang.Class.getMethod(Class.java:1784)
	at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:650)
	at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:632)
Caused by: java.lang.ClassNotFoundException: java.lang.constant.Constable
	at java.net.URLClassLoader.findClass(URLClassLoader.java:387)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:419)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:352)
	... 19 more

Examining the emitted class file, Foo.class, shows that java.lang.constant.Constable is included
as an interface implemented by the Foo class, even though the JDK set as the target JDK does not have this
class:

javap -p -v Foo.class 
Classfile /.../constable-bug/bin/Foo.class
  Last modified 10 Jan. 2023; size 14263 bytes
  MD5 checksum 4167f8e08e0d5fdc3eed3fc303ec6629
  Compiled from "Foo.groovy"
public class Foo implements java.io.Serializable,java.lang.Comparable,java.lang.CharSequence,java.lang.constant.Constable,java.lang.constant.ConstantDesc,groovy.lang.GroovyObject
  minor version: 0
  major version: 52
...

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions