Search code examples
androidjvmdalviktermuxkawa

`java.lang.NoClassDefFoundError: android/view/View` while trying to build 'HelloWorld' project from android-kawa in Termux


I've been trying to employ Kawa Scheme for developing Android project. I've found two repositories on GitHub: one called 'android-kawa', and another called 'KawaDroid'. They're both a bit dated (last updates were around 2012). In the case of 'android-kawa' I was able to reach the author, but he said he did't remeber enough to help me.

In the 'android-kawa' repo there's a bunch of scripts for setting up and working with the project. One of the scripts downloads the Kawa 1.13 tarball, applies some patches and then attempts to build it.

However, the build isn't supported in Termux, bevaise the config.guess script doesn't recognize the system. This issue can be easily resolved by downloading the latest versions of config.guess and config.sub.

Another problem is the format of the JVM bytecode. When I use the latest Java compiler, the generated bytecode contains (I believe) instructions for JVM8+, which aren't supported by the dx command. This isn't a problem if I run Java inside of Termux, because it installs the regular JVM, but if I want to include the Kawa jar in my APK (which is something that I want), then it becomes an obstacle.

This, again, can be resolved by forcing the Java version to 7 in javac. (But then, the compiler complsins that Java 1.7 is deprecated. I guess this is why the buildAPKs project uses ecj instead of javac)

Also, when I ./configure Kawa, I can pass it the path to the android.jar file (./configure --with-android=...). I have two android.jar files on my system:

~ $ locate android.jar
/data/data/com.termux/files/usr/share/aapt/android.jar
/data/data/com.termux/files/usr/share/java/android.jar

I don't know where they came from or how they differ between one another, but I've been prefering the second one.

So, when I have the kawa.jar available - and when I try to compile it with the command

~/android-kawa $ java -cp $(dirname $(locate android.jar |tail -n 1)) -jar kawa/kawa-1.13.jar -C  KawaHello/src/kawa/android/hello.scm

I get the following error:

internal error while compiling KawaHello/src/kawa/android/hello.scm
java.lang.NoClassDefFoundError: android/view/View
        at gnu.kawa.android.defs.<clinit>(defs.scm)
        at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized0(Native Method)
        at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized(Unsafe.java:1155)
        at java.base/jdk.internal.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(UnsafeFieldAccessorFactory.java:42)
        at java.base/jdk.internal.reflect.ReflectionFactory.newFieldAccessor(ReflectionFactory.java:185)
        at java.base/java.lang.reflect.Field.acquireFieldAccessor(Field.java:1132)
        at java.base/java.lang.reflect.Field.getFieldAccessor(Field.java:1113)
        at java.base/java.lang.reflect.Field.get(Field.java:425)
        at gnu.expr.ModuleInfo.setupModuleExp(ModuleInfo.java:195)
        at kawa.standard.require.importDefinitions(require.java:308)
        at kawa.standard.require.scanForDefinitions(require.java:219)
        at kawa.lang.Syntax.scanForm(Syntax.java:65)
        at kawa.lang.Translator.scanForm(Translator.java:1120)
        at gnu.kawa.lispexpr.LispLanguage.parse(LispLanguage.java:64)
        at gnu.expr.Compilation.process(Compilation.java:1908)
        at gnu.expr.ModuleInfo.loadByStages(ModuleInfo.java:305)
        at gnu.expr.ModuleInfo.loadByStages(ModuleInfo.java:290)
        at gnu.expr.ModuleInfo.loadByStages(ModuleInfo.java:290)
        at gnu.expr.ModuleInfo.loadByStages(ModuleInfo.java:290)
        at gnu.expr.ModuleInfo.loadByStages(ModuleInfo.java:290)
        at gnu.expr.ModuleInfo.loadByStages(ModuleInfo.java:290)
        at kawa.repl.compileFiles(repl.java:823)
        at kawa.repl.processArgs(repl.java:444)
        at kawa.repl.main(repl.java:869)
Caused by: java.lang.ClassNotFoundException: android.view.View
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)                                                            at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)         ... 24 more

I have obviously tried it without the -cp argument (with the same effect). The android/view/View.class entry is present in the list returned by jar -tf android.jar.

How can I further investigate in the root cause of the problem, and most importantly, how can I solve it?


Solution

  • It turned out that I have invoked Java incorrectly, and that it didn't see the android.jar file. It helped to invoke the compiler in the following way:

    ~/android-kawa $ java -cp $(locate android.jar |tail -n 1):kawa/kawa-1.13.jar kawa.repl -C KawaHello/src/kawa/android/hello.scm
    

    (the difference is that I only have one -cp argument with jar files separated by :, and that I explicitly give the kawa.repl class name)