ClassDefNotFoundError - org.languagetool.language.AmericanEnglish

Hello all,

I am attempting to make an Android app which imports the LanguageTool java library and detects English grammatical errors.

Despite importing languagetool.jar, I am receiving a ClassDefNotFoundError on org.languagetool.language.AmericanEnglish upon instantiating an AmericanEnglish object. This error only occurs when I try to import LanguageTool in an Android app. When importing the same jar into a java file on my machine, this error does not occur.

Is there another jar I need to import? Why would this be happening?

Thanks

If you’ve downloaded the ZIP, AmericanEnglish.class is not in a JAR, but in the “org” directory. You can ZIP that directory and name it languagetool-2.jar or whatever and it should work. However, if at all possible, I would recommend to use Maven, as documented at Java API - LanguageTool Wiki.

Thank you very much!

I have gotten past the ClassDefNotFoundError, although I am now experiencing a NullPointerException upon initialization of JLanguageTool. My Android error log is telling me that I am getting a NullPointerException in JLanguageTool.getBuildDate (line 111). I have a hunch that this may be related to what appears to be getBuildDate’s attempt to open an internet connection.

My code to initialize JLanguageTool is the following:

Language lang = new AmericanEnglish();
_langTool = new JLanguageTool(lang);

My Android error log is the following:

02-20 03:03:36.414: I/dalvikvm(1408): Could not find method java.util.Objects.requireNonNull, referenced from method org.languagetool.JLanguageTool.
02-20 03:03:36.414: W/dalvikvm(1408): VFY: unable to resolve static method 5737: Ljava/util/Objects;.requireNonNull (Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;
02-20 03:03:36.414: D/dalvikvm(1408): VFY: replacing opcode 0x71 at 0x0028
02-20 03:03:36.429: W/dalvikvm(1408): Exception Ljava/lang/NullPointerException; thrown while initializing Lorg/languagetool/JLanguageTool;
02-20 03:03:36.429: D/AndroidRuntime(1408): Shutting down VM
02-20 03:03:36.429: W/dalvikvm(1408): threadid=1: thread exiting with uncaught exception (group=0x40dd11f8)
02-20 03:03:36.437: E/AndroidRuntime(1408): FATAL EXCEPTION: main
02-20 03:03:36.437: E/AndroidRuntime(1408): java.lang.ExceptionInInitializerError
02-20 03:03:36.437: E/AndroidRuntime(1408): at com.openllamatalk.helloglass.Magic.onActivityResult(Magic.java:254)
02-20 03:03:36.437: E/AndroidRuntime(1408): at android.app.Activity.dispatchActivityResult(Activity.java:4654)
02-20 03:03:36.437: E/AndroidRuntime(1408): at android.app.ActivityThread.deliverResults(ActivityThread.java:2976)
02-20 03:03:36.437: E/AndroidRuntime(1408): at android.app.ActivityThread.handleSendResult(ActivityThread.java:3023)
02-20 03:03:36.437: E/AndroidRuntime(1408): at android.app.ActivityThread.access$1100(ActivityThread.java:123)
02-20 03:03:36.437: E/AndroidRuntime(1408): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1177)
02-20 03:03:36.437: E/AndroidRuntime(1408): at android.os.Handler.dispatchMessage(Handler.java:99)
02-20 03:03:36.437: E/AndroidRuntime(1408): at android.os.Looper.loop(Looper.java:137)
02-20 03:03:36.437: E/AndroidRuntime(1408): at android.app.ActivityThread.main(ActivityThread.java:4424)
02-20 03:03:36.437: E/AndroidRuntime(1408): at java.lang.reflect.Method.invokeNative(Native Method)
02-20 03:03:36.437: E/AndroidRuntime(1408): at java.lang.reflect.Method.invoke(Method.java:511)
02-20 03:03:36.437: E/AndroidRuntime(1408): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
02-20 03:03:36.437: E/AndroidRuntime(1408): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
02-20 03:03:36.437: E/AndroidRuntime(1408): at dalvik.system.NativeStart.main(Native Method)
02-20 03:03:36.437: E/AndroidRuntime(1408): Caused by: java.lang.NullPointerException
02-20 03:03:36.437: E/AndroidRuntime(1408): at org.languagetool.JLanguageTool.getBuildDate(JLanguageTool.java:111)
02-20 03:03:36.437: E/AndroidRuntime(1408): at org.languagetool.JLanguageTool.(JLanguageTool.java:90)
02-20 03:03:36.437: E/AndroidRuntime(1408): … 14 more
~

Again, thank you very much!

It’s not opening an internet connection, but looking for a file “org/languagetool/JLanguageTool.class”, which is usually in a JAR. Maybe the getResource() works differently on Android and cannot find the class for some reason. I suggest you search the web if there is some special behavior in Android for getResource(). I needed, I’ll just return null on Android.

Ah, this seems to explain the problem:

One user from this thread posted:
“I am not 100% sure but I don’t think that this mechanism works under Android as it does in a real JVM (since dalvik is essentially not a JVM). I think (and I might be wrong here), that in the packaged APK, the JAR does no longer exist and therefore your path to the resource probably is wrong. The classes of your JAR are converted to the dex file format and added to the classes.dex file. Therefore you cannot resolve a resource like foo.bar.class because it does not exist in the classpath.”

So, it seems that for now I should locally modify getBuildDate to return null? I would prefer this to the cost of having another internet connection request in my app.

I have modified getBuildDate() so it will not crash but return null on Android. You can find the change in our nightly builds in a few hours:

https://languagetool.org/download/snapshots/?C=M;O=D

Thanks so much! I will report back once I test out the nightly build.

The good news is that I am no longer getting any exceptions related to getBuildDate(). However, now my app is refusing to recognize the java.util.Objects class which is clearly contained in my android jar. I believe my my classpath order is set appropriately, so I do not see why this is an issue.

My error log is the following:

02-20 20:35:58.328: I/dalvikvm(4701): Could not find method java.util.Objects.requireNonNull, referenced from method org.languagetool.JLanguageTool.
02-20 20:35:58.328: W/dalvikvm(4701): VFY: unable to resolve static method 5830: Ljava/util/Objects;.requireNonNull (Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;
02-20 20:35:58.328: D/dalvikvm(4701): VFY: replacing opcode 0x71 at 0x0028
02-20 20:35:58.343: D/AndroidRuntime(4701): Shutting down VM
02-20 20:35:58.343: W/dalvikvm(4701): threadid=1: thread exiting with uncaught exception (group=0x40dc21f8)
02-20 20:35:58.351: E/AndroidRuntime(4701): FATAL EXCEPTION: main
02-20 20:35:58.351: E/AndroidRuntime(4701): java.lang.NoClassDefFoundError: java.util.Objects
02-20 20:35:58.351: E/AndroidRuntime(4701): at org.languagetool.JLanguageTool.(JLanguageTool.java:195)
02-20 20:35:58.351: E/AndroidRuntime(4701): at org.languagetool.JLanguageTool.(JLanguageTool.java:182)
02-20 20:35:58.351: E/AndroidRuntime(4701): at com.openllamatalk.helloglass.Magic.onActivityResult(Magic.java:254)
02-20 20:35:58.351: E/AndroidRuntime(4701): at android.app.Activity.dispatchActivityResult(Activity.java:4654)
02-20 20:35:58.351: E/AndroidRuntime(4701): at android.app.ActivityThread.deliverResults(ActivityThread.java:2976)
02-20 20:35:58.351: E/AndroidRuntime(4701): at android.app.ActivityThread.handleSendResult(ActivityThread.java:3023)
02-20 20:35:58.351: E/AndroidRuntime(4701): at android.app.ActivityThread.access$1100(ActivityThread.java:123)
02-20 20:35:58.351: E/AndroidRuntime(4701): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1177)
02-20 20:35:58.351: E/AndroidRuntime(4701): at android.os.Handler.dispatchMessage(Handler.java:99)
02-20 20:35:58.351: E/AndroidRuntime(4701): at android.os.Looper.loop(Looper.java:137)
02-20 20:35:58.351: E/AndroidRuntime(4701): at android.app.ActivityThread.main(ActivityThread.java:4424)
02-20 20:35:58.351: E/AndroidRuntime(4701): at java.lang.reflect.Method.invokeNative(Native Method)
02-20 20:35:58.351: E/AndroidRuntime(4701): at java.lang.reflect.Method.invoke(Method.java:511)
02-20 20:35:58.351: E/AndroidRuntime(4701): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
02-20 20:35:58.351: E/AndroidRuntime(4701): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
02-20 20:35:58.351: E/AndroidRuntime(4701): at dalvik.system.NativeStart.main(Native Method)

java.util.Objects was introduced with Java 1.7. If Android still only support Java 1.6, that’s a problem. You could use LanguageTool 2.2, which was the latest version of LanguageTool that still works with Java 1.6.

Hi Laura, did you succeed in getting LT to work on Android?

I did, thank you!

I ended up playing around a bit with version 2.2 to get it to finally work. I had to make a few edits, such as changing the ways that model files (i.e. grammar.xml) are read in such that they could be read from an Android apk.

The latency for detecting errors in one 5-7 word sentence on Android (Google Glass, specifically) is surprisingly good. I’m looking at around a 0.5-1 second wait time.

Do you initialize LanguageTool only once and then call check(…) per sentence? The initialization takes a lot of time, doing that only once should make things faster.

Will the software be published somewhere?

Yes, I do the initialization only once.

Right now, my code is available publicly on Github, and I’m in the stage of cleaning it up. I would be happy to share this after I see that it’s in a presentable state.
I have my LanguageTool jar available on Github as part of the libraries required for my app, but I do not have my code modifications to LanguageTool available publicly. Is this something you would be interested in?

Yes, we’re interested in the changes you needed to make. You might also fork LT on github and apply your changes there, that’s easier than keeping the changes locally.