Search code examples
javaexceptionstanford-nlp

IncompatibleClassChangeError while running Stanford NER and Stanford POS tagger


I am trying to use Stanford NER and Stanford POS tagger in one application. I am getting IncompatibleClassChangeError when I try to run POS tagger method.

I have jar files of both NER and POS tagger in the class path. If I remove jar of NER from my classpath then this error is not coming. I guess there are some classes common in NER jar and POS jar and java is not able to determine which class to be used at runtime.

Following is the stacktrace :

java.lang.IncompatibleClassChangeError: Implementing class
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(Unknown Source)
    at java.security.SecureClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.access$000(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClassInternal(Unknown Source)
    at edu.stanford.nlp.tagger.maxent.MaxentTagger.init(MaxentTagger.java:407)
    at edu.stanford.nlp.tagger.maxent.MaxentTagger.readModelAndInit(MaxentTagger.java:699)
    at edu.stanford.nlp.tagger.maxent.MaxentTagger.readModelAndInit(MaxentTagger.java:673)
    at edu.stanford.nlp.tagger.maxent.MaxentTagger.<init>(MaxentTagger.java:280)
    at edu.stanford.nlp.tagger.maxent.MaxentTagger.<init>(MaxentTagger.java:260)
    at edu.stanford.nlp.tagger.maxent.MaxentTagger.runTagger(MaxentTagger.java:1305)
    at edu.stanford.nlp.tagger.maxent.MaxentTagger.main(MaxentTagger.java:1499)
    at com.tcs.srl.stanford.POSWrapper.executePOSTagger(POSWrapper.java:39)
    at com.tcs.srl.stanford.test.POSWrapperTester.ExecutePOSTagger(POSWrapperTester.java:19)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

I have no clue why this error is coming.


Solution

  • I think you are close but not quite right in your diagnosis. Java will always use the first instance of a class in your classpath. However, if you have a heirarchy of classloaders, and a child classloader tries to define a class that a parent has already defined you will get an error like this.

    I'm not familiar with the Stanford NER or POS code. However, I can offer some advice.

    If you are convinced the classes with the same names are identical in the two jars, then just combine the two jars into a single jar - this will remove any duplicates.

    If you are worried the NER and POS code might be incompatible, I'd move the source code for the two into a single project, and recompile, carefully inspecting the duplicates.

    The alternative is to take the source code from one project and move it into a different package so the class names stay the same, but the packages no longer clash. A good IDE should be able to do this fairly painlessly.

    However, for issues like this mailing lists are often the best place to get advice: http://www-nlp.stanford.edu/software/CRF-NER.shtml. I'm sure you won't be the only person to be using these pieces of software together. None of the solutions I mention above should be necessary, so getting advice from someone else who uses them is probably the best.