summaryrefslogtreecommitdiffstats
path: root/src/java/jogamp/android/launcher/ClassLoaderUtil.java
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-01-31 21:15:32 +0100
committerSven Gothel <[email protected]>2013-01-31 21:15:32 +0100
commitb47d0d92dd222999bf38633de1cec8de6a7ad369 (patch)
tree764afc7741b6cb5cf3a11f5d4a8d3c117b3b5f0e /src/java/jogamp/android/launcher/ClassLoaderUtil.java
parentc8de8fbf5d080b674b509763fbb7374c21ee705b (diff)
Android: Cleanup ClassLoaderUtil/LauncherUtil - Using cached parent ClassLoader for SYS-Packages w/ native libs, and non cached child ClassLoader for USR-Packages
Android's Dalvik VM, like a JVM, cannot load a native library from one location by multiple ClassLoader. Since we don't like to hardcode the system-packages, as it was before, i.e. "com.jogamp.common", "javax.media.opengl", we need to either copy the libs or use parenting of cached ClassLoader. The latter is chosen, since it's faster and uses less resources. - System-packages are passed through from the user 'List<String> LauncherUtil.BaseActivityLauncher::getSysPackages()' to the ActivityLauncher, which instantiates the ClassLoader. - No more hard-reference the system-packages in ClassLoaderUtil ("com.jogamp.common", "javax.media.opengl"), just use the new user provided system-packages. - The system-packages denominate a hash-key for caching, a new ClassLoader is created and mapped if it does not yet exist. - A non-chached user-packages ClassLoader is created using the cached system-packages ClassLoader as it's parent.
Diffstat (limited to 'src/java/jogamp/android/launcher/ClassLoaderUtil.java')
-rw-r--r--src/java/jogamp/android/launcher/ClassLoaderUtil.java70
1 files changed, 46 insertions, 24 deletions
diff --git a/src/java/jogamp/android/launcher/ClassLoaderUtil.java b/src/java/jogamp/android/launcher/ClassLoaderUtil.java
index ae2918f..76dbf53 100644
--- a/src/java/jogamp/android/launcher/ClassLoaderUtil.java
+++ b/src/java/jogamp/android/launcher/ClassLoaderUtil.java
@@ -29,7 +29,7 @@
package jogamp.android.launcher;
import java.io.File;
-import java.util.Arrays;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -41,15 +41,13 @@ import android.util.Log;
public class ClassLoaderUtil {
private static final String TAG = "JogampClassLoader";
- // FIXME: Need to generalize this .. (Note: native lib resources must be cached!)
- private static final String[] packagesJogAmp = { "com.jogamp.common", "javax.media.opengl" };
- private static ClassLoader jogAmpClassLoader = null;
+ private static HashMap<String, ClassLoader> cachedClassLoader = new HashMap<String, ClassLoader>();
// location where optimized dex files will be written
private static final String dexPathName= "jogampDex";
private static File dexPath = null;
- private static LauncherTempFileCache tmpFileCache = null;
+ private static LauncherTempFileCache tmpFileCache = null;
private static final String PATH_SEP = "/";
private static final String ELEM_SEP = ":";
@@ -69,45 +67,69 @@ public class ClassLoaderUtil {
}
}
- public static synchronized ClassLoader createClassLoader(Context ctx, List<String> userPackageNames, boolean addUserLibPath,
- List<String> apkNames) {
- return createClassLoader(ctx, userPackageNames, addUserLibPath, apkNames, null);
+ /**
+ * @param ctx
+ * @param cachedPackageName list of package names w/ native libraries for which a ClassLoader shall be cached, i.e. persistence.
+ * This is usually required for native libraries.
+ * @param userPackageNames list of user package names w/o native libraries, the last entry shall reflect the Activity.
+ * @param userAPKNames optional non-cached user APKs
+ * @return
+ */
+ public static synchronized ClassLoader createClassLoader(Context ctx, List<String> cachedPackageName,
+ List<String> userPackageNames, List<String> userAPKNames) {
+ return createClassLoader(ctx, cachedPackageName, userPackageNames, userAPKNames, null);
}
- public static synchronized ClassLoader createClassLoader(Context ctx, List<String> userPackageNames, boolean addUserLibPath,
- List<String> apkNames, ClassLoader parent) {
+ /**
+ * @param ctx
+ * @param cachedPackageNames list of package names w/ native libraries for which a ClassLoader shall be cached, i.e. persistence.
+ * This is usually required for native libraries.
+ * @param userPackageNames list of user package names w/o native libraries, the last entry shall reflect the Activity.
+ * @param userAPKNames optional non-cached user APKs
+ * @param parent
+ * @return
+ */
+ public static synchronized ClassLoader createClassLoader(Context ctx, List<String> cachedPackageNames,
+ List<String> userPackageNames, List<String> userAPKNames,
+ ClassLoader parent) {
init(ctx);
- if(null==jogAmpClassLoader) {
- jogAmpClassLoader = createClassLoaderImpl(ctx, Arrays.asList(packagesJogAmp), true, null,
- (null != parent ) ? parent : ctx.getClassLoader());
+ final String cacheKey = cachedPackageNames.toString();
+ ClassLoader clCached = cachedClassLoader.get(cacheKey);
+ if( null == clCached ) {
+ clCached = createClassLoaderImpl(ctx, cachedPackageNames, true, null, (null != parent ) ? parent : ctx.getClassLoader());
+ cachedClassLoader.put(cacheKey, clCached);
+ Log.d(TAG, "NEW cached-CL: cachedPackageNames: "+cacheKey);
+ } else {
+ Log.d(TAG, "REUSE cached-CL: cachedPackageNames: "+cacheKey);
}
- parent = jogAmpClassLoader;
- return createClassLoaderImpl(ctx, userPackageNames, addUserLibPath, apkNames, jogAmpClassLoader);
+ return createClassLoaderImpl(ctx, userPackageNames, false, userAPKNames, clCached);
}
/**
- *
* @param ctx
- * @param userPackageNames list of user package names, the last entry shall reflect the Activity
+ * @param packageNames list of package names
+ * @param addLibPath
+ * @param apkNames
+ * @param parent
* @return
*/
- private static synchronized ClassLoader createClassLoaderImpl(Context ctx, List<String> userPackageNames, boolean addUserLibPath,
+ private static synchronized ClassLoader createClassLoaderImpl(Context ctx, List<String> packageNames, boolean addLibPath,
List<String> apkNames, ClassLoader parent) {
final ApplicationInfo appInfoLauncher= ctx.getApplicationInfo();
final String appDirLauncher = new File(appInfoLauncher.dataDir).getParent();
final String libSubDef = "lib";
- Log.d(TAG, "S: userPackageNames: "+userPackageNames+"; Launcher: appDir "+appDirLauncher+", dataDir: "+appInfoLauncher.dataDir+", nativeLibraryDir "+appInfoLauncher.nativeLibraryDir);
+ Log.d(TAG, "S: userPackageNames: "+packageNames+"; Launcher: appDir "+appDirLauncher+", dataDir: "+appInfoLauncher.dataDir+", nativeLibraryDir "+appInfoLauncher.nativeLibraryDir);
final StringBuilder apks = new StringBuilder();
final StringBuilder libs = new StringBuilder();
int apkCount = 0;
String lastUserPackageName = null; // the very last one reflects the Activity
- if( null != userPackageNames ) {
- for(Iterator<String> i=userPackageNames.iterator(); i.hasNext(); ) {
+ if( null != packageNames ) {
+ for(Iterator<String> i=packageNames.iterator(); i.hasNext(); ) {
lastUserPackageName = i.next();
String userAPK = null;
@@ -125,14 +147,14 @@ public class ClassLoaderUtil {
if(null != userAPK) {
if(apkCount>0) {
apks.append(ELEM_SEP);
- if(addUserLibPath) {
+ if(addLibPath) {
libs.append(ELEM_SEP);
}
}
apks.append(userAPK);
Log.d(TAG, "APK["+apkCount+"] found: <"+lastUserPackageName+"> -> <"+userAPK+">");
Log.d(TAG, "APK["+apkCount+"] apks: <"+apks.toString()+">");
- if(addUserLibPath) {
+ if(addLibPath) {
if(null != nativeLibraryDir && nativeLibraryDir.length()>0 ) {
libs.append(nativeLibraryDir).append(PATH_SEP);
} else {
@@ -145,7 +167,7 @@ public class ClassLoaderUtil {
Log.d(TAG, "APK not found: <"+lastUserPackageName+">");
}
}
- if( userPackageNames.size() != apkCount ) {
+ if( packageNames.size() != apkCount ) {
Log.d(TAG, "User APKs incomplete, abort (1)");
return null;
}