My favorites | Sign in
Project Home Issues
New issue   Search
for
  Advanced search   Search tips   Subscriptions
Issue 5697: getContextClassLoader returns a non-application classloader
12 people starred this issue and may be notified of changes. Back to list
Status:  Released
Owner:  b...@google.com
Closed:  Feb 2010
Cc:  e...@google.com, jessewil...@google.com, b...@google.com

Restricted
  • Only users with Commit permission may comment.


Sign in to add a comment
 
Reported by li...@sibvisions.org, Dec 29, 2009
Tried to play with the standard logging API: java.util.logging and
configured it through logging.properties. I have written my own Formatter
and configured it for the ConsoleHandler!
(I know that the log output goes to System.err and not to the "logcat", but
that's not the problem)


my logging.properties:

handlers = java.util.logging.ConsoleHandler

java.util.logging.ConsoleHandler.level = ALL
java.util.logging.ConsoleHandler.formatter = com.sibvisions.android.LogFormat

com.sibvisions.level = ALL


The LogFormat is a test class (don't wonder):

package com.sibvisions.android;

import java.util.logging.Formatter;
import java.util.logging.LogRecord;

public class LogFormat extends Formatter
{
	@Override
    public synchronized String format(LogRecord pRecord) 
    {
		return pRecord.getSourceClassName();
    }
}

My test activity:

public class AndroidClient extends Activity
{
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		
		InputStream isProp = getClass().getResourceAsStream("/logging.properties");

		try
		{
			LogManager.getLogManager().readConfiguration(isProp);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		
		Logger lg = Logger.getLogger(getClass().getName());
		
		lg.log(Level.SEVERE, "TEST", new Exception());
    }
}

I got the following exception:

12-29 11:52:05.548: WARN/System.err(1720): java.util.logging.ErrorManager:
GENERIC_FAILURE
12-29 11:52:05.558: WARN/System.err(1720): Error message - Invalid property
value for
java.util.logging.ConsoleHandler:formatter/com.sibvisions.android.LogFormat
12-29 11:52:05.558: WARN/System.err(1720): Exception -
java.security.PrivilegedActionException: java.lang.ClassNotFoundException:
com.sibvisions.android.LogFormat in loader
dalvik.system.PathClassLoader@4001b500


Reproduced it with the code from:
java.util.logging.Handler.getCustomizeInstance()


		try
		{
  		Class<?> c = AccessController.doPrivileged(new
PrivilegedExceptionAction<Class<?>>() {
		public Class<?> run() throws Exception {
		ClassLoader loader = Thread.currentThread()
		.getContextClassLoader();
		if (null == loader) {
		loader = ClassLoader.getSystemClassLoader();
		}
//OK
		Class.forName("com.sibvisions.android.LogFormat");

System.out.println(loader.getClass().getName() +" - "+
Class.class.getClassLoader().getClass().getName());		

//ERROR		
		return loader.loadClass("com.sibvisions.android.LogFormat");
		}
		});
		
		c.newInstance();				
		}
		catch (Exception e)
		{
			Log.v("TAG", Log.getStackTraceString(e));
		}

Dec 29, 2009
#1 li...@sibvisions.org
API Version 2.0.1
(device independent problem)
Dec 29, 2009
#2 e...@google.com
(No comment was entered for this change.)
Owner: jessewil...@google.com
Cc: enh+...@google.com
Labels: Component-Dalvik
Jan 21, 2010
#3 jessewil...@google.com
(No comment was entered for this change.)
Summary: getContextClassLoader returns a non-application classloader
Owner: jessewil...@google.com
Cc: -enh+...@google.com e...@google.com
Jan 25, 2010
Project Member #4 b...@google.com
(No comment was entered for this change.)
Cc: b...@google.com
Feb 25, 2010
Project Member #5 b...@google.com
This problem was because Thread.getContextClassLoader() was returning null, causing your class to 
be loaded by the ClassLoader.getSystemClassLoader which does not know about your application 
classes, which is why it fails to find the class.

When you use Class.forName from your own code, it uses the ClassLoader of the code invoking 
Class.forName, which explains why it can find your class.

The workaround is to set the Java context class loader in your Activity.onCreate as described here:
https://code.google.com/p/dalvik/wiki/JavaxPackages

I've commited a fix for Froyo that sets the Java context class loader automatically for the common 
case of having a single application in a virtual machine so that things should work right for most 
people and the won't need to use any workaround.

We do not set the Thread local Java context class loader to the APK classpath in all cases. 
Specifically if you have have arranged in your AndroidManifest.xml to allow multiple APKs to be run 
in the same virtual machine. In this case, it would be ambiguous which to use as the Thread local 
context class loader, and in fact it could vary from run to run depending the loading order of the 
multiple packages. However, in this case we now set the context class loader to a pass through 
ClassLoader that will warn that you probably need to set the context class loader if you are going 
to use libraries that do make use of Java context class loader.

Note that Java's Thread.getContextClassLoader should not be confused with 
android.content.Context.getClassLoader. While now in the common case these will be the same, using 
your Android Context (e.g. Activity) class is designed to let you load classes associated with a 
specific context even if the virtual machine has multiple APKs loaded. In general in Android code 
you should use the Context.getClassLoader, although it is useful to have 
Thread.getContextClassLoader work to support existing Java libraries that rely on its mechanism to 
load custom application classes.

Status: FutureRelease
Owner: b...@google.com
Cc: -b...@google.com jessewil...@google.com
Labels: Target-Froyo
Dec 6, 2010
Project Member #6 e...@google.com
(No comment was entered for this change.)
Status: Released
Dec 3, 2012
Project Member #7 e...@google.com
(No comment was entered for this change.)
Labels: Restrict-AddIssueComment-Commit
Sign in to add a comment

Powered by Google Project Hosting