• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.inject.internal;
18 
19 import static com.google.inject.internal.InternalFlags.getCustomClassLoadingOption;
20 
21 import com.google.common.cache.CacheBuilder;
22 import com.google.common.cache.CacheLoader;
23 import com.google.common.cache.LoadingCache;
24 import com.google.inject.internal.InternalFlags.CustomClassLoadingOption;
25 import java.lang.reflect.Constructor;
26 import java.lang.reflect.Member;
27 import java.lang.reflect.Method;
28 import java.lang.reflect.Modifier;
29 import java.security.AccessController;
30 import java.security.PrivilegedAction;
31 import java.util.logging.Level;
32 import java.util.logging.Logger;
33 
34 /**
35  * Utility methods for runtime code generation and class loading. We use this stuff for {@link
36  * net.sf.cglib.reflect.FastClass faster reflection}, {@link net.sf.cglib.proxy.Enhancer method
37  * interceptors} and to proxy circular dependencies.
38  *
39  * <p>When loading classes, we need to be careful of:
40  *
41  * <ul>
42  * <li><strong>Memory leaks.</strong> Generated classes need to be garbage collected in long-lived
43  *     applications. Once an injector and any instances it created can be garbage collected, the
44  *     corresponding generated classes should be collectable.
45  * <li><strong>Visibility.</strong> Containers like <code>OSGi</code> use class loader boundaries to
46  *     enforce modularity at runtime.
47  * </ul>
48  *
49  * <p>For each generated class, there's multiple class loaders involved:
50  *
51  * <ul>
52  * <li><strong>The related class's class loader.</strong> Every generated class services exactly one
53  *     user-supplied class. This class loader must be used to access members with protected and
54  *     package visibility.
55  * <li><strong>Guice's class loader.</strong>
56  * <li><strong>Our bridge class loader.</strong> This is a child of the user's class loader. It
57  *     selectively delegates to either the user's class loader (for user classes) or the Guice class
58  *     loader (for internal classes that are used by the generated classes). This class loader that
59  *     owns the classes generated by Guice.
60  * </ul>
61  *
62  * @author mcculls@gmail.com (Stuart McCulloch)
63  * @author jessewilson@google.com (Jesse Wilson)
64  */
65 public final class BytecodeGen {
66 
67   static final Logger logger = Logger.getLogger(BytecodeGen.class.getName());
68 
69   static final ClassLoader GUICE_CLASS_LOADER = canonicalize(BytecodeGen.class.getClassLoader());
70 
71   // initialization-on-demand...
72   private static class SystemBridgeHolder {
73     static final BridgeClassLoader SYSTEM_BRIDGE = new BridgeClassLoader();
74   }
75 
76   /** ie. "com.google.inject.internal" */
77   static final String GUICE_INTERNAL_PACKAGE =
78       BytecodeGen.class.getName().replaceFirst("\\.internal\\..*$", ".internal");
79 
80   /*if[AOP]*/
81   /** either "net.sf.cglib", or "com.google.inject.internal.cglib" */
82   static final String CGLIB_PACKAGE =
83       net.sf.cglib.proxy.Enhancer.class.getName().replaceFirst("\\.cglib\\..*$", ".cglib");
84 
85   static final net.sf.cglib.core.NamingPolicy FASTCLASS_NAMING_POLICY =
86       new net.sf.cglib.core.DefaultNamingPolicy() {
87         @Override
88         protected String getTag() {
89           return "ByGuice";
90         }
91 
92         @Override
93         public String getClassName(
94             String prefix, String source, Object key, net.sf.cglib.core.Predicate names) {
95           // we explicitly set the source here to "FastClass" so that our jarjar renaming
96           // to $FastClass doesn't leak into the class names.  if we did not do this,
97           // classes would end up looking like $$$FastClassByGuice$$, with the extra $
98           // at the front.
99           return super.getClassName(prefix, "FastClass", key, names);
100         }
101       };
102 
103   static final net.sf.cglib.core.NamingPolicy ENHANCER_NAMING_POLICY =
104       new net.sf.cglib.core.DefaultNamingPolicy() {
105         @Override
106         protected String getTag() {
107           return "ByGuice";
108         }
109 
110         @Override
111         public String getClassName(
112             String prefix, String source, Object key, net.sf.cglib.core.Predicate names) {
113           // we explicitly set the source here to "Enhancer" so that our jarjar renaming
114           // to $Enhancer doesn't leak into the class names.  if we did not do this,
115           // classes would end up looking like $$$EnhancerByGuice$$, with the extra $
116           // at the front.
117           return super.getClassName(prefix, "Enhancer", key, names);
118         }
119       };
120   /*end[AOP]*/
121   /*if[NO_AOP]
122   private static final String CGLIB_PACKAGE = " "; // any string that's illegal in a package name
123   end[NO_AOP]*/
124 
125   /**
126    * Weak cache of bridge class loaders that make the Guice implementation classes visible to
127    * various code-generated proxies of client classes.
128    */
129   private static final LoadingCache<ClassLoader, ClassLoader> CLASS_LOADER_CACHE;
130 
131   static {
132     CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder().weakKeys().weakValues();
133     if (getCustomClassLoadingOption() == CustomClassLoadingOption.OFF) {
134       builder.maximumSize(0);
135     }
136     CLASS_LOADER_CACHE =
137         builder.build(
138             new CacheLoader<ClassLoader, ClassLoader>() {
139               @Override
140               public ClassLoader load(final ClassLoader typeClassLoader) {
141                 logger.fine("Creating a bridge ClassLoader for " + typeClassLoader);
142                 return AccessController.doPrivileged(
143                     new PrivilegedAction<ClassLoader>() {
144                       @Override
145                       public ClassLoader run() {
146                         return new BridgeClassLoader(typeClassLoader);
147                       }
148                     });
149               }
150             });
151   }
152 
153   /**
154    * Attempts to canonicalize null references to the system class loader. May return null if for
155    * some reason the system loader is unavailable.
156    */
canonicalize(ClassLoader classLoader)157   private static ClassLoader canonicalize(ClassLoader classLoader) {
158     return classLoader != null ? classLoader : SystemBridgeHolder.SYSTEM_BRIDGE.getParent();
159   }
160 
161   /** Returns the class loader to host generated classes for {@code type}. */
getClassLoader(Class<?> type)162   public static ClassLoader getClassLoader(Class<?> type) {
163     return getClassLoader(type, type.getClassLoader());
164   }
165 
getClassLoader(Class<?> type, ClassLoader delegate)166   private static ClassLoader getClassLoader(Class<?> type, ClassLoader delegate) {
167 
168     // simple case: do nothing!
169     if (getCustomClassLoadingOption() == CustomClassLoadingOption.OFF) {
170       return delegate;
171     }
172 
173     // java.* types can be seen everywhere
174     if (type.getName().startsWith("java.")) {
175       return GUICE_CLASS_LOADER;
176     }
177 
178     delegate = canonicalize(delegate);
179 
180     // no need for a bridge if using same class loader, or it's already a bridge
181     if (delegate == GUICE_CLASS_LOADER || delegate instanceof BridgeClassLoader) {
182       return delegate;
183     }
184 
185     // don't try bridging private types as it won't work
186     if (Visibility.forType(type) == Visibility.PUBLIC) {
187       if (delegate != SystemBridgeHolder.SYSTEM_BRIDGE.getParent()) {
188         // delegate guaranteed to be non-null here
189         return CLASS_LOADER_CACHE.getUnchecked(delegate);
190       }
191       // delegate may or may not be null here
192       return SystemBridgeHolder.SYSTEM_BRIDGE;
193     }
194 
195     return delegate; // last-resort: do nothing!
196   }
197 
198   /*if[AOP]*/
199   // use fully-qualified names so imports don't need preprocessor statements
200   /**
201    * Returns a FastClass proxy for invoking the given member or {@code null} if access rules
202    * disallow it.
203    *
204    * @see #newFastClassForMember(Class, Member) for a full description
205    */
newFastClassForMember(Member member)206   public static net.sf.cglib.reflect.FastClass newFastClassForMember(Member member) {
207     return newFastClassForMember(member.getDeclaringClass(), member);
208   }
209 
210   /**
211    * Returns a FastClass proxy for invoking the given member or {@code null} if access rules
212    * disallow it.
213    *
214    * <p>FastClass works by generating a type in the same package as the target {@code type}. This
215    * may or may not work depending on the access level of the class/member. It breaks down into the
216    * following cases depending on accessibility:
217    *
218    * <ul>
219    * <li>Public: This always works since we can generate the type into the {@link BridgeClassLoader}
220    *     which ensures there are no versioning issues.
221    * <li>Package private and Protected: This works as long as:
222    *     <ul>
223    *     <li>We can generate into the same classloader as the type. This is not possible for JDK
224    *         types which use the 'bootstrap' loader.
225    *     <li>The classloader of the type has the same version of {@code FastClass} as we do. This
226    *         may be violated when running in OSGI bundles.
227    *     </ul>
228    *
229    * <li>Private: This never works.
230    * </ul>
231    *
232    * If we are unable to generate the type, then we return null and callers should work around by
233    * using normal java reflection.
234    */
newFastClassForMember(Class<?> type, Member member)235   public static net.sf.cglib.reflect.FastClass newFastClassForMember(Class<?> type, Member member) {
236     if (!new net.sf.cglib.core.VisibilityPredicate(type, false).evaluate(member)) {
237       // the member cannot be indexed by fast class.  Bail out.
238       return null;
239     }
240 
241     boolean publiclyCallable = isPubliclyCallable(member);
242     if (!publiclyCallable && !hasSameVersionOfCglib(type.getClassLoader())) {
243       // The type is in a classloader with a different version of cglib and is not publicly visible
244       // (so we can't use the bridge classloader to work around).  Bail out.
245       return null;
246     }
247     net.sf.cglib.reflect.FastClass.Generator generator =
248         new net.sf.cglib.reflect.FastClass.Generator();
249     if (publiclyCallable) {
250       // Use the bridge classloader if we can
251       generator.setClassLoader(getClassLoader(type));
252     }
253     generator.setType(type);
254     generator.setNamingPolicy(FASTCLASS_NAMING_POLICY);
255     if (logger.isLoggable(Level.FINE)) {
256       logger.fine("Loading " + type + " FastClass with " + generator.getClassLoader());
257     }
258     return generator.create();
259   }
260 
261   /**
262    * Returns true if the types classloader has the same version of cglib that BytecodeGen has. This
263    * only returns false in strange OSGI situations, but it prevents us from using FastClass for non
264    * public members.
265    */
hasSameVersionOfCglib(ClassLoader classLoader)266   private static boolean hasSameVersionOfCglib(ClassLoader classLoader) {
267     Class<?> fc = net.sf.cglib.reflect.FastClass.class;
268     try {
269       return classLoader.loadClass(fc.getName()) == fc;
270     } catch (ClassNotFoundException e) {
271       return false;
272     }
273   }
274 
275   /**
276    * Returns true if the member can be called by a fast class generated in a different classloader.
277    */
isPubliclyCallable(Member member)278   private static boolean isPubliclyCallable(Member member) {
279     if (!Modifier.isPublic(member.getModifiers())) {
280       return false;
281     }
282     Class<?>[] parameterTypes;
283     if (member instanceof Constructor) {
284       parameterTypes = ((Constructor) member).getParameterTypes();
285     } else {
286       Method method = (Method) member;
287       if (!Modifier.isPublic(method.getReturnType().getModifiers())) {
288         return false;
289       }
290       parameterTypes = method.getParameterTypes();
291     }
292 
293     for (Class<?> type : parameterTypes) {
294       if (!Modifier.isPublic(type.getModifiers())) {
295         return false;
296       }
297     }
298     return true;
299   }
300 
newEnhancer(Class<?> type, Visibility visibility)301   public static net.sf.cglib.proxy.Enhancer newEnhancer(Class<?> type, Visibility visibility) {
302     net.sf.cglib.proxy.Enhancer enhancer = new net.sf.cglib.proxy.Enhancer();
303     enhancer.setSuperclass(type);
304     enhancer.setUseFactory(false);
305     if (visibility == Visibility.PUBLIC) {
306       enhancer.setClassLoader(getClassLoader(type));
307     }
308     enhancer.setNamingPolicy(ENHANCER_NAMING_POLICY);
309     logger.fine("Loading " + type + " Enhancer with " + enhancer.getClassLoader());
310     return enhancer;
311   }
312   /*end[AOP]*/
313 
314   /**
315    * The required visibility of a user's class from a Guice-generated class. Visibility of
316    * package-private members depends on the loading classloader: only if two classes were loaded by
317    * the same classloader can they see each other's package-private members. We need to be careful
318    * when choosing which classloader to use for generated classes. We prefer our bridge classloader,
319    * since it's OSGi-safe and doesn't leak permgen space. But often we cannot due to visibility.
320    */
321   public enum Visibility {
322 
323     /**
324      * Indicates that Guice-generated classes only need to call and override public members of the
325      * target class. These generated classes may be loaded by our bridge classloader.
326      */
327     PUBLIC {
328       @Override
and(Visibility that)329       public Visibility and(Visibility that) {
330         return that;
331       }
332     },
333 
334     /**
335      * Indicates that Guice-generated classes need to call or override package-private members.
336      * These generated classes must be loaded in the same classloader as the target class. They
337      * won't work with OSGi, and won't get garbage collected until the target class' classloader is
338      * garbage collected.
339      */
340     SAME_PACKAGE {
341       @Override
and(Visibility that)342       public Visibility and(Visibility that) {
343         return this;
344       }
345     };
346 
forMember(Member member)347     public static Visibility forMember(Member member) {
348       if ((member.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) == 0) {
349         return SAME_PACKAGE;
350       }
351 
352       Class[] parameterTypes;
353       if (member instanceof Constructor) {
354         parameterTypes = ((Constructor) member).getParameterTypes();
355       } else {
356         Method method = (Method) member;
357         if (forType(method.getReturnType()) == SAME_PACKAGE) {
358           return SAME_PACKAGE;
359         }
360         parameterTypes = method.getParameterTypes();
361       }
362 
363       for (Class<?> type : parameterTypes) {
364         if (forType(type) == SAME_PACKAGE) {
365           return SAME_PACKAGE;
366         }
367       }
368 
369       return PUBLIC;
370     }
371 
forType(Class<?> type)372     public static Visibility forType(Class<?> type) {
373       return (type.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) != 0
374           ? PUBLIC
375           : SAME_PACKAGE;
376     }
377 
and(Visibility that)378     public abstract Visibility and(Visibility that);
379   }
380 
381   /**
382    * Loader for Guice-generated classes. For referenced classes, this delegates to either either the
383    * user's classloader (which is the parent of this classloader) or Guice's class loader.
384    */
385   private static class BridgeClassLoader extends ClassLoader {
386 
BridgeClassLoader()387     BridgeClassLoader() {
388       // use system loader as parent
389     }
390 
BridgeClassLoader(ClassLoader usersClassLoader)391     BridgeClassLoader(ClassLoader usersClassLoader) {
392       super(usersClassLoader);
393     }
394 
395     @Override
loadClass(String name, boolean resolve)396     protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
397 
398       if (name.startsWith("sun.reflect") || name.startsWith("jdk.internal.reflect")) {
399         // these reflection classes must be loaded from bootstrap class loader
400         return SystemBridgeHolder.SYSTEM_BRIDGE.classicLoadClass(name, resolve);
401       }
402 
403       if (name.startsWith(GUICE_INTERNAL_PACKAGE) || name.startsWith(CGLIB_PACKAGE)) {
404         if (null == GUICE_CLASS_LOADER) {
405           // use special system bridge to load classes from bootstrap class loader
406           return SystemBridgeHolder.SYSTEM_BRIDGE.classicLoadClass(name, resolve);
407         }
408         try {
409           Class<?> clazz = GUICE_CLASS_LOADER.loadClass(name);
410           if (resolve) {
411             resolveClass(clazz);
412           }
413           return clazz;
414         } catch (Throwable e) {
415           // fall-back to classic delegation
416         }
417       }
418 
419       return classicLoadClass(name, resolve);
420     }
421 
422     // make the classic delegating loadClass method visible
classicLoadClass(String name, boolean resolve)423     Class<?> classicLoadClass(String name, boolean resolve) throws ClassNotFoundException {
424       return super.loadClass(name, resolve);
425     }
426   }
427 }
428