Question

I am writing an eclipse plugin to support the Frege programming language. I use the IMP meta tooling platform and Eclipse Indigo (3.7). The run time environment is Java 1.7.

The plugin uses the same code as the batch compiler for token parsing, syntax analysis, etc. However, I noticed differing behavior when run from the eclipse plugin and traced it down to the following method that reads a class file of a previously compiled module to get meta-information which is stored there in form of java annotations:

public static MD.Operator[] getOperators(ClassLoader loader, String pack) 
                                              throws ClassNotFoundException {
    Class<?> cl = null;
    cl = loader.loadClass(pack);
    MD.FregePackage os = cl.getAnnotation(MD.FregePackage.class);
    if (os == null) return null;        // <-- no annotation present
    return os.ops();
}    

Note that the code creates its own instance of an URLClassLoader, which is passed as argument. If I do not set the class path correctly, the getOperators method correctly throws a ClassNotFoundException, therefore I think I can be sure that it loads the class. A trace message tells me that the class loader is built with the following path (which is just the classpath by default):

mkClassLoader:[C:\opt\eclipse\plugins\org.eclipse.equinox.launcher_1.2.0.v20110502.jar, X:\dev\frege\build]

Because a class file not created by the frege compiler cannot normally have the MD.FregePackage annotation this usually indicates that the user tried to import a plain java class, and indeed I get the following message in the plugin:

X:/dev/runtime-EclipseApplication/TestJFrege/src/Neu.fr:1: `frege.prelude.Base` is not a frege package

Yet, from the command line I can compile this just fine. I included this here as proof that the annotations in question can indeed be loaded from the same location:

X:\dev\frege>java -cp ./build frege.compiler.Main X:/dev/runtimeEclipseApplication/TestJFrege/src/Neu.fr
mkClassLoader: [./build]
running: javac -cp ./build -d . -encoding UTF-8 ./Neu.java

Resuming the facts:

  1. The code that is supposed to load the annotations works fine when the compiler is invoked via command line interface.
  2. The code that is supposed to load the annotations does not know whether it is invoked from the plugin or the command line. In fact, the plugin didn't even exist until last week, while the command line interface used to work fine for months.
  3. The annotations have, of course, RetentionPolicy.RUNTIME otherwise the command line compilation would not recognize them either. But it proovably does.

So the only conclusion I can draw is that Class.getAnnotation() somehow is not working correctly. This is very unfortunate, as this effectively destroys basic functionality I need for the module system.

If this matters anyhow: the Frege compiler code the plugin uses is itself written in Frege and the frege.prelude.Base class mentioned above is a basic library that is needed by every module, hence it must already have been loaded on activation of the plugin, though of course with a different class loader.

Does anybody have similar experiences? Is it possible to solve this and how? Any suggestions how to circumvent this are welcome.

Was it helpful?

Solution

Was the MD.FregePackage class loaded by the classloader used in your method? Possibly try loading that one first, since two classes aren't equal() if they were loaded by different class loaders. That could explain why it isn't being found.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top