From 4985c5c782661c2fd0ae6c368062b5203222c087 Mon Sep 17 00:00:00 2001 From: Mathew Inwood Date: Thu, 31 Dec 2015 12:28:54 +0000 Subject: [PATCH] Experimental: verify cached constructors before use. Caching constructors can cause problems for dynamically loaded code if the same class name appears in more than on classloader. Before using cached constructors, verifty that they come from a valid classloader, i.e. one that appears in the classloader chain of the current contexts classloader. Remove ones that do not from the map to allow the associated classes to be unloaded in case they're no longer in use. Bug: 21690610 Change-Id: I84f2894cd03a5dc0c33aed9cd710e4a1f6d9515f --- core/java/android/view/LayoutInflater.java | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java index aa29636398e49..914bd5684b4ab 100644 --- a/core/java/android/view/LayoutInflater.java +++ b/core/java/android/view/LayoutInflater.java @@ -555,6 +555,26 @@ public abstract class LayoutInflater { } } + private static final ClassLoader BOOT_CLASS_LOADER = LayoutInflater.class.getClassLoader(); + + private final boolean verifyClassLoader(Constructor constructor) { + final ClassLoader constructorLoader = constructor.getDeclaringClass().getClassLoader(); + if (constructorLoader == BOOT_CLASS_LOADER) { + // fast path for boot class loader (most common case?) - always ok + return true; + } + // in all normal cases (no dynamic code loading), we will exit the following loop on the + // first iteration (i.e. when the declaring classloader is the contexts class loader). + ClassLoader cl = mContext.getClassLoader(); + do { + if (constructorLoader == cl) { + return true; + } + cl = cl.getParent(); + } while (cl != null); + return false; + } + /** * Low-level function for instantiating a view by name. This attempts to * instantiate a view class of the given name found in this @@ -575,6 +595,10 @@ public abstract class LayoutInflater { public final View createView(String name, String prefix, AttributeSet attrs) throws ClassNotFoundException, InflateException { Constructor constructor = sConstructorMap.get(name); + if (constructor != null && !verifyClassLoader(constructor)) { + constructor = null; + sConstructorMap.remove(name); + } Class clazz = null; try {