Search code examples
javaeclipseclasspatheclipse-jdt

Eclipse JDT class ASTVisitor not found


Consider the following code:

// App.java
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.SimpleName;

public class App
{
    public static void main(String[] args)
    {
        ASTVisitor visitor = new ASTVisitor()
            {
                public boolean visit(VariableDeclarationFragment node)
                {
                    return false;
                }
                public boolean visit(SimpleName node)
                {
                    return false;
                }
            };
    }
}

compiled successfully with:

$ javac -cp org.eclipse.jdt.core.jar App.java

Library org.eclipse.jdt.core.jar is copied from the latest release of Eclipse. When running this program:

$ java App -cp org.eclipse.jdt.core.jar

I get the following runtime error:

Exception in thread "main" java.lang.NoClassDefFoundError: org/eclipse/jdt/core/dom/ASTVisitor
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
...

Actually this is a stripped-down version of another test program where dependencies are managed with Maven, and giving the same error. Looking for a solution, I found hints that this may be related to missing dependencies, or dependencies not loaded in the correct order. However, I don't understand how this could be happening. Inspecting the used jar I get:

$ jar tf org.eclipse.jdt.core.jar | grep ASTVisitor
org/eclipse/jdt/core/dom/DefaultASTVisitor.class
org/eclipse/jdt/core/dom/ASTVisitor.class
org/eclipse/jdt/internal/compiler/ASTVisitor.class

so the actual class is indeed there. In addition to this, I tried loading a bunch of related classes, as suggested by this link, and then I tried again loading all JDT classes that come with the Eclipse installation, but unfortunately with no result.

What can be the problem and what else can I do to track it down?

Thank you very much.


Solution

  • Thanks to greg-449 for spotting the command-line usage error. After fixing that, I was able to successfully run that example.

    After some other trials, I found that, for some reason, these programs that use Eclipse JDT fail to run even after being successfully compiled, unless I add to the class path the jars directly taken from an actual Eclipse installation. This means that I could successfully run my program (the more complex one) compiled using Maven dependencies, after I added the Eclipse jars to the class path:

    $ cd my-project/
    $ mvn install
    $ cd target
    $ java -cp "myprogram.jar:../lib/*" path.to.my.main.Class
    

    where lib contains a bunch of jars coming from my Eclipse installation.

    EDIT

    Actually it's not necessary to link Eclipse jar files at all. In fact everything works correctly when using maven-exec-plugin instead of directly call the java command:

    $ mvn exec:java -Dexec.mainClass=path.to.my.main.Class
    

    Thinking a bit about it, it seems now obvious that Maven automatically links the project dependencies' jar files, downloaded in ~/.m2 during the installation, when I call the command mvn exec:java. Probably I could have got the same result adding to the classpath the jars stored in ~/.m2 instead of manually copying those provided with my Eclipse installation.