Alex Yarygin Alex Yarygin - 1 month ago 22
Java Question

Android application throws Guice exception

I'm new in Android applcation and probably do something wrong.
I've tried to compile application with javampd modue but it throws an Exception: "com.google.inject.internal.util.$ComputationException: com.google.inject.internal.util.$ComputationException: java.lang.ExceptionInInitializerError" at the biulder creation:

try {
MPD.Builder mpdBuilder = new MPD.Builder();
} catch (Exception error) {
String text = error.getMessage();
Toast.makeText(this, "Exception: " + text, Toast.LENGTH_LONG).show();
}


I've traced the exception up to Guice and figured out that exception is throwing inside javampd module

injector = Guice.createInjector(new MPDModule());


Here is full stack trace:

W/nalizableReferenceQueue: Could not load Finalizer in its own class loader. Loading Finalizer in the current class loader instead. As a result, you will not be able to garbage collect this class loader. To support reclaiming this class loader, either resolve the underlying issue, or move Google Collections to your system class path.
java.io.FileNotFoundException: com/google/inject/internal/util/$Finalizer.class
at com.google.inject.internal.util.$FinalizableReferenceQueue$DecoupledLoader.getBaseUrl(FinalizableReferenceQueue.java:269)
at com.google.inject.internal.util.$FinalizableReferenceQueue$DecoupledLoader.loadFinalizer(FinalizableReferenceQueue.java:253)
at com.google.inject.internal.util.$FinalizableReferenceQueue.loadFinalizer(FinalizableReferenceQueue.java:175)
at com.google.inject.internal.util.$FinalizableReferenceQueue.<clinit>(FinalizableReferenceQueue.java:100)
at com.google.inject.internal.util.$MapMaker$QueueHolder.<clinit>(MapMaker.java:787)
at com.google.inject.internal.util.$MapMaker$WeakEntry.<init>(MapMaker.java:946)
at com.google.inject.internal.util.$MapMaker$Strength$1.newEntry(MapMaker.java:312)
at com.google.inject.internal.util.$MapMaker$StrategyImpl.newEntry(MapMaker.java:498)
at com.google.inject.internal.util.$MapMaker$StrategyImpl.newEntry(MapMaker.java:419)
at com.google.inject.internal.util.$CustomConcurrentHashMap$ComputingImpl.get(CustomConcurrentHashMap.java:2029)
at com.google.inject.internal.Annotations$AnnotationChecker.hasAnnotations(Annotations.java:116)
at com.google.inject.internal.Annotations.isScopeAnnotation(Annotations.java:124)
at com.google.inject.internal.ScopeBindingProcessor.visit(ScopeBindingProcessor.java:40)
at com.google.inject.internal.ScopeBindingProcessor.visit(ScopeBindingProcessor.java:30)
at com.google.inject.spi.ScopeBinding.acceptVisitor(ScopeBinding.java:59)
at com.google.inject.internal.AbstractProcessor.process(AbstractProcessor.java:55)
at com.google.inject.internal.InjectorShell$Builder.build(InjectorShell.java:165)
at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:103)
at com.google.inject.Guice.createInjector(Guice.java:95)
at com.google.inject.Guice.createInjector(Guice.java:72)
at com.google.inject.Guice.createInjector(Guice.java:62)
at org.bff.javampd.MPD$Builder.<init>(MPD.java:186)
at com.yarygin.alex.mpd_test.MainActivity.onCreate(MainActivity.java:16)
at android.app.Activity.performCreate(Activity.java:5971)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1111)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2413)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2522)
at android.app.ActivityThread.access$800(ActivityThread.java:167)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1417)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5534)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:955)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:750)


My gradle file:

apply plugin: 'com.android.application'

android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "com.yarygin.alex.mpd_test"
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}

dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:22.2.1'
testCompile 'junit:junit:4.12'
compile 'net.thejavashop:javampd:5.0.3'
}


And my Activity file:

package com.yarygin.alex.mpd_test;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

import org.bff.javampd.MPD;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

try {
MPD.Builder mpdBuilder = new MPD.Builder();
} catch (Exception error) {
String text = error.getMessage();
Toast.makeText(this, "Exception: " + text, Toast.LENGTH_LONG).show();
}
}
}


I can not find the reason in two weeks. Please help!

Answer

Although Android apps are written in Java, you often cannot simply take Java libraries and use them in an Android app without configuration issues.

If that library, Java MPD, depends internally on Guice, it will be difficult to use as-is inside an Android project. This is because Guice has a number of configuration issues for working with Android. Besides, there are some other issues to consider. To demonstrate, I quote from the FAQ of one of the other DI frameworks for Android:

  1. Guice is slow, at least it didn't match any more the expected performance of Android apps.
  2. Guice 4 uses Guava which contains tens of thousands of methods that contribute to multidex issues and heavy apks
  3. Guice uses reflection and reflection is especially slow on Android. Mostly because there is no JIT of reflection code as opposed to PC JVMs.

You could try using Roboguice, which uses a fork of Guice and an annotations processor to get around Guice's use of reflection and other integration issues with Android. If that provides enough of the Guice classes to make your MDP library work I would be surprised. Otherwise, you will have to find another library to use.