Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ReflectionException: Cannot read class file for some JDK9 classes #152

Closed
don-vip opened this issue Sep 1, 2016 · 19 comments
Closed

ReflectionException: Cannot read class file for some JDK9 classes #152

don-vip opened this issue Sep 1, 2016 · 19 comments
Labels
Milestone

Comments

@don-vip
Copy link
Contributor

don-vip commented Sep 1, 2016

What steps will reproduce the problem?

Run JOSM JUnit tests with JDK9: https://josm.openstreetmap.de/jenkins/job/Java-EarlyAccess-JOSM/jdk=JDK9/lastCompletedBuild/testReport/

What is the code that triggers this problem? (first case)

@FunctionalInterface
public interface Destroyable {
    void destroy();
}

public abstract class JosmAction extends javax.swing.AbstractAction implements Destroyable {
}

public class CombineWayAction extends JosmAction {

    /**
     * A pair of nodes.
     */
    public static class NodePair {
        private final Node a;
        private final Node b;

        /**
         * Constructs a new {@code NodePair}.
         * @param a The first node
         * @param b The second node
         */
        public NodePair(Node a, Node b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public int hashCode() {
            return Objects.hash(a, b);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (obj == null || getClass() != obj.getClass()) return false;
            NodePair nodePair = (NodePair) obj;
            return Objects.equals(a, nodePair.a) && Objects.equals(b, nodePair.b);
        }
    }
}

    /**
     * Unit test of methods {@link NodePair#equals} and {@link NodePair#hashCode}.
     */
    @Test
    public void testEqualsContract() {
        EqualsVerifier.forClass(NodePair.class).usingGetClass()
            .withPrefabValues(Node.class, new Node(1), new Node(2))
            .verify();
    }

What is the code that triggers this problem? (second case)

public class ExtensionFileFilter extends javax.swing.filechooser.FileFilter implements java.io.FileFilter {

    private final String extensions;
    private final String description;
    private final String defaultExtension;

    @Override
    public int hashCode() {
        return Objects.hash(extensions, description, defaultExtension);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        ExtensionFileFilter that = (ExtensionFileFilter) obj;
        return Objects.equals(extensions, that.extensions) &&
               Objects.equals(description, that.description) &&
               Objects.equals(defaultExtension, that.defaultExtension);
    }
}

    /**
     * Unit test of methods {@link ExtensionFileFilter#equals} and {@link ExtensionFileFilter#hashCode}.
     */
    @Test
    public void testEqualsContract() {
        EqualsVerifier.forClass(ExtensionFileFilter.class).usingGetClass()
            .verify();
    }

What error message or stack trace does EqualsVerifier give?

junit.framework.AssertionFailedError: ReflectionException: Cannot read class file for AbstractAction.
Suppress Warning.ANNOTATION to skip annotation processing phase.
    at nl.jqno.equalsverifier.EqualsVerifier.handleError(EqualsVerifier.java:381)
    at nl.jqno.equalsverifier.EqualsVerifier.verify(EqualsVerifier.java:370)
    at org.openstreetmap.josm.actions.CombineWayActionTest.testEqualsContract(CombineWayActionTest.java:67)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base@9-ea/Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base@9-ea/NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@9-ea/DelegatingMethodAccessorImpl.java:43)

junit.framework.AssertionFailedError: ReflectionException: Cannot read class file for FileFilter.
Suppress Warning.ANNOTATION to skip annotation processing phase.
    at nl.jqno.equalsverifier.EqualsVerifier.handleError(EqualsVerifier.java:381)
    at nl.jqno.equalsverifier.EqualsVerifier.verify(EqualsVerifier.java:370)
    at org.openstreetmap.josm.actions.ExtensionFileFilterTest.testEqualsContract(ExtensionFileFilterTest.java:45)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base@9-ea/Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base@9-ea/NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@9-ea/DelegatingMethodAccessorImpl.java:43)

What did you expect?

Test success, like with JDK8

Which version of EqualsVerifier are you using?

2.1.5

Please provide any additional information below.

Complete source code:
https://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/actions/CombineWayAction.java
https://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/actions/ExtensionFileFilter.java

@jqno
Copy link
Owner

jqno commented Sep 4, 2016

Hi,

Thanks for reporting this. Unfortunately, I haven't had time to investigate Java 9 yet. I've just installed it, and I can reproduce your problem. I managed to reduce it to the following little program:

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Type;

import java.io.InputStream;

public class Example {
    public static void main(String[] args) throws Exception {
        Class<?> c = javax.swing.filechooser.FileFilter.class;
//        Class<?> c = Example.class;
        ClassLoader cl = ClassLoader.getSystemClassLoader();
        Type asmType = Type.getType(c);
        String url = asmType.getInternalName() + ".class";
        System.out.println(asmType + " -- " + url);
        InputStream is = cl.getResourceAsStream(url);
        new ClassReader(is);
    }
}

(It depends on ASM 5.1.)

The program terminates without problem om Java 8, but it throws this exception on Java 9:

Ljavax/swing/filechooser/FileFilter; -- javax/swing/filechooser/FileFilter.class
Exception in thread "main" java.io.IOException: Class not found
    at org.objectweb.asm.ClassReader.a(Unknown Source)
    at org.objectweb.asm.ClassReader.<init>(Unknown Source)
    at Example.main(Example.java:15)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base@9-ea/Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base@9-ea/NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@9-ea/DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(java.base@9-ea/Method.java:535)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

Process finished with exit code 1

It does the same thing for other types provided by Java (such as java.lang.String), but it does work for user-defined classes (such as Example itself).

ASM has released an alpha version that supports Java 9, but there's no official release yet. Although I can imagine that the problem lies in the way I get hold of a class loader; probably lots of things have changed here due to Project Jigsaw.

In other words, I'll have to find some time to investigate this further. If you have some ideas about this, or if you can point me to some good resources to read up on this, I'd be very grateful 😄 .

In the mean time, you can work around the issue by suppressing Warning.ANNOTATION (though you've probably already figured that out yourself.)

@jqno jqno added the accepted label Sep 4, 2016
@don-vip
Copy link
Contributor Author

don-vip commented Sep 4, 2016

Thanks for the heads up! FYI we already use ASM 6.0_Alpha with Findbugs 3.1.0_preview2 and we didn't notice any error.

@jqno
Copy link
Owner

jqno commented Sep 4, 2016

Perhaps the particular use case that I use ASM for, doesn't come up with FindBugs. I tried replacing EqualsVerifier's version of ASM with the 6.0_ALPHA, but that didn't work, unfortunately.

I'll let you know when I find a solution.

@jqno
Copy link
Owner

jqno commented Oct 1, 2016

I have good news and bad news.
The good news is, I have found a way to solve this issue. Upgrading to ASM 6.0_ALPHA was necessary, but not enough. I have some proof-of-concept grade code that fixes the problem, though.
The bad news is, I can't release it, for several reasons. The most important one is that both JaCoCo and the Maven Shade plugin crash when they encounter the new ASM jar. Looks like they can't handle Java 9 class files and/or jars yet...

I'm attaching the patch file to this issue, so you can try it out locally if you like, and so that I won't forget about it when these issues are fixed :). Keep in mind though, this is still proof of concept code; I wouldn't release this code in the state it's in now. Use at your own risk ;).

issue-152-java-9.patch.txt

@don-vip
Copy link
Contributor Author

don-vip commented Oct 1, 2016

Did you try Jacoco 0.7.7 or latest snapshot of 0.7.8? We currently use 0.7.8 snapshot to get Java 9 fixes, see jacoco/jacoco#434

@jqno
Copy link
Owner

jqno commented Oct 1, 2016

I used Jacoco 0.7.7. I could indeed try the snapshot, but I can (and do) work around it by simply compiling from Java 7 or 8. EqualsVerifier needs to be compatible with all three anyway. Not being able to do Jacoco from Java 9 is very inconvenient, but the real show stopper is the Maven Shade plugin. Without that, I can't build a jar file to publish on Maven Central.

If you have a workaround for that as well, I'd be very grateful :).

@jqno
Copy link
Owner

jqno commented Oct 3, 2016

Found the issue in Apache's Jira: https://issues.apache.org/jira/browse/MSHADE-234

@don-vip
Copy link
Contributor Author

don-vip commented May 25, 2017

According to https://issues.apache.org/jira/browse/MSHADE-242 they are also waiting for the next ASM release to support Java 9.

@jqno
Copy link
Owner

jqno commented May 30, 2017

I tried reproducing this issue today, and upgrading to ASM 6.0_ALPHA fixes it. I don't even need the patch anymore that I mentioned before, so that's a plus. However, I'm not comfortable relying on this ALPHA release. I'd rather wait until there's a final version.

The JaCoCo issue has been resolved; Maven Shade is indeed also still waiting on a final release for ASM 6.0.

@don-vip
Copy link
Contributor Author

don-vip commented May 30, 2017

I agree it's best to wait. Oracle has the obligation to release the final draft of JPMS (module system) next week, we can hope for a new release of ASM not long after, as the maintainer is also in the Expert Group :)

@don-vip
Copy link
Contributor Author

don-vip commented Jul 16, 2017

ASM 6.0 beta is released! https://mail.ow2.org/wws/arc/asm/2017-07/msg00002.html

@jqno
Copy link
Owner

jqno commented Jul 18, 2017

Thanks for the heads-up!

I'll play around with it. If they come up with a final version soon, I'll try to have a Java 9 compatible version soon after. If it takes a while longer, I may release a beta version of EqualsVerifier based on ASM's beta in the mean time. It depends a little on when I have time to work on it.

@don-vip
Copy link
Contributor Author

don-vip commented Aug 4, 2017

ASM 6.0 beta is finally available on Maven Central: https://twitter.com/rfscholte/status/893511314575851521

@jqno
Copy link
Owner

jqno commented Aug 4, 2017

Again, thanks for the heads-up; we've been waiting for this for quite a while :). I'll try it out this weekend!

@jqno
Copy link
Owner

jqno commented Aug 6, 2017

I just released version 2.3.2 which uses ASM 6.0_BETA as a dependency. It passes all my tests. Could you give it a try and see if it works for you too?

@don-vip
Copy link
Contributor Author

don-vip commented Aug 6, 2017

Yes, it works! Thanks a lot!

@don-vip don-vip closed this as completed Aug 6, 2017
@jqno
Copy link
Owner

jqno commented Aug 6, 2017

I'm very glad to hear that! Thanks for your help :).

@don-vip
Copy link
Contributor Author

don-vip commented Aug 22, 2017

Maven Shade plugin 3.1.0 is available, see tcurdt/jdependency#11 (comment) :)

@jqno
Copy link
Owner

jqno commented Aug 23, 2017

Thanks for letting me know about this! I upgraded, and it works like a charm.

floscher pushed a commit to floscher/josm that referenced this issue Oct 12, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants