• 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 
26 import java.lang.reflect.Constructor;
27 import java.lang.reflect.Member;
28 import java.lang.reflect.Method;
29 import java.lang.reflect.Modifier;
30 import java.security.AccessController;
31 import java.security.PrivilegedAction;
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  * <ul>
41  *   <li><strong>Memory leaks.</strong> Generated classes need to be garbage collected in long-lived
42  *       applications. Once an injector and any instances it created can be garbage collected, the
43  *       corresponding generated classes should be collectable.
44  *   <li><strong>Visibility.</strong> Containers like <code>OSGi</code> use class loader boundaries
45  *       to enforce modularity at runtime.
46  * </ul>
47  *
48  * <p>For each generated class, there's multiple class loaders involved:
49  * <ul>
50  *    <li><strong>The related class's class loader.</strong> Every generated class services exactly
51  *        one user-supplied class. This class loader must be used to access members with private and
52  *        package visibility.
53  *    <li><strong>Guice's class loader.</strong>
54  *    <li><strong>Our bridge class loader.</strong> This is a child of the user's class loader. It
55  *        selectively delegates to either the user's class loader (for user classes) or the Guice
56  *        class loader (for internal classes that are used by the generated classes). This class
57  *        loader that owns the classes generated by Guice.
58  * </ul>
59  *
60  * @author mcculls@gmail.com (Stuart McCulloch)
61  * @author jessewilson@google.com (Jesse Wilson)
62  */
63 public final class BytecodeGen {
64 
65   static final Logger logger = Logger.getLogger(BytecodeGen.class.getName());
66 
67   static final ClassLoader GUICE_CLASS_LOADER = canonicalize(BytecodeGen.class.getClassLoader());
68 
69   // initialization-on-demand...
70   private static class SystemBridgeHolder {
71     static final BridgeClassLoader SYSTEM_BRIDGE = new BridgeClassLoader();
72   }
73 
74   /** ie. "com.google.inject.internal" */
75   static final String GUICE_INTERNAL_PACKAGE
76       = BytecodeGen.class.getName().replaceFirst("\\.internal\\..*$", ".internal");
77 
78   /*if[AOP]*/
79   /** either "net.sf.cglib", or "com.google.inject.internal.cglib" */
80   static final String CGLIB_PACKAGE
81       = net.sf.cglib.proxy.Enhancer.class.getName().replaceFirst("\\.cglib\\..*$", ".cglib");
82 
83   static final net.sf.cglib.core.NamingPolicy FASTCLASS_NAMING_POLICY
84       = new net.sf.cglib.core.DefaultNamingPolicy() {
85     @Override protected String getTag() {
86       return "ByGuice";
87     }
88 
89     @Override
90     public String getClassName(String prefix, String source, Object key,
91         net.sf.cglib.core.Predicate names) {
92       // we explicitly set the source here to "FastClass" so that our jarjar renaming
93       // to $FastClass doesn't leak into the class names.  if we did not do this,
94       // classes would end up looking like $$$FastClassByGuice$$, with the extra $
95       // at the front.
96       return super.getClassName(prefix, "FastClass", key, names);
97     }
98   };
99 
100   static final net.sf.cglib.core.NamingPolicy ENHANCER_NAMING_POLICY
101       = new net.sf.cglib.core.DefaultNamingPolicy() {
102     @Override
103     protected String getTag() {
104       return "ByGuice";
105     }
106 
107     @Override
108     public String getClassName(String prefix, String source, Object key,
109         net.sf.cglib.core.Predicate names) {
110       // we explicitly set the source here to "Enhancer" so that our jarjar renaming
111       // to $Enhancer doesn't leak into the class names.  if we did not do this,
112       // classes would end up looking like $$$EnhancerByGuice$$, with the extra $
113       // at the front.
114       return super.getClassName(prefix, "Enhancer", key, names);
115     }
116   };
117   /*end[AOP]*/
118   /*if[NO_AOP]
119   private static final String CGLIB_PACKAGE = " "; // any string that's illegal in a package name
120   end[NO_AOP]*/
121 
122   /**
123    * Weak cache of bridge class loaders that make the Guice implementation
124    * classes visible to various code-generated proxies of client classes.
125    */
126   private static final LoadingCache<ClassLoader, ClassLoader> CLASS_LOADER_CACHE;
127 
128   static {
129     CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder().weakKeys().weakValues();
130     if (getCustomClassLoadingOption() == CustomClassLoadingOption.OFF) {
131       builder.maximumSize(0);
132     }
133     CLASS_LOADER_CACHE = builder.build(
134         new CacheLoader<ClassLoader, ClassLoader>() {
135           @Override public ClassLoader load(final ClassLoader typeClassLoader) {
136             logger.fine("Creating a bridge ClassLoader for " + typeClassLoader);
137             return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
138               public ClassLoader run() {
139                 return new BridgeClassLoader(typeClassLoader);
140               }
141             });
142           }
143         });
144   }
145 
146   /**
147    * Attempts to canonicalize null references to the system class loader.
148    * May return null if for some reason the system loader is unavailable.
149    */
canonicalize(ClassLoader classLoader)150   private static ClassLoader canonicalize(ClassLoader classLoader) {
151     return classLoader != null ? classLoader : SystemBridgeHolder.SYSTEM_BRIDGE.getParent();
152   }
153 
154   /**
155    * Returns the class loader to host generated classes for {@code type}.
156    */
getClassLoader(Class<?> type)157   public static ClassLoader getClassLoader(Class<?> type) {
158     return getClassLoader(type, type.getClassLoader());
159   }
160 
getClassLoader(Class<?> type, ClassLoader delegate)161   private static ClassLoader getClassLoader(Class<?> type, ClassLoader delegate) {
162 
163     // simple case: do nothing!
164     if (getCustomClassLoadingOption() == CustomClassLoadingOption.OFF) {
165       return delegate;
166     }
167 
168     // java.* types can be seen everywhere
169     if (type.getName().startsWith("java.")) {
170       return GUICE_CLASS_LOADER;
171     }
172 
173     delegate = canonicalize(delegate);
174 
175     // no need for a bridge if using same class loader, or it's already a bridge
176     if (delegate == GUICE_CLASS_LOADER || delegate instanceof BridgeClassLoader) {
177       return delegate;
178     }
179 
180     // don't try bridging private types as it won't work
181     if (Visibility.forType(type) == Visibility.PUBLIC) {
182       if (delegate != SystemBridgeHolder.SYSTEM_BRIDGE.getParent()) {
183         // delegate guaranteed to be non-null here
184         return CLASS_LOADER_CACHE.getUnchecked(delegate);
185       }
186       // delegate may or may not be null here
187       return SystemBridgeHolder.SYSTEM_BRIDGE;
188     }
189 
190     return delegate; // last-resort: do nothing!
191   }
192 
193   /*if[AOP]*/
194   // use fully-qualified names so imports don't need preprocessor statements
newFastClass(Class<?> type, Visibility visibility)195   public static net.sf.cglib.reflect.FastClass newFastClass(Class<?> type, Visibility visibility) {
196     net.sf.cglib.reflect.FastClass.Generator generator
197         = new net.sf.cglib.reflect.FastClass.Generator();
198     generator.setType(type);
199     if (visibility == Visibility.PUBLIC) {
200       generator.setClassLoader(getClassLoader(type));
201     }
202     generator.setNamingPolicy(FASTCLASS_NAMING_POLICY);
203     logger.fine("Loading " + type + " FastClass with " + generator.getClassLoader());
204     return generator.create();
205   }
206 
newEnhancer(Class<?> type, Visibility visibility)207   public static net.sf.cglib.proxy.Enhancer newEnhancer(Class<?> type, Visibility visibility) {
208     net.sf.cglib.proxy.Enhancer enhancer = new net.sf.cglib.proxy.Enhancer();
209     enhancer.setSuperclass(type);
210     enhancer.setUseFactory(false);
211     if (visibility == Visibility.PUBLIC) {
212       enhancer.setClassLoader(getClassLoader(type));
213     }
214     enhancer.setNamingPolicy(ENHANCER_NAMING_POLICY);
215     logger.fine("Loading " + type + " Enhancer with " + enhancer.getClassLoader());
216     return enhancer;
217   }
218   /*end[AOP]*/
219 
220   /**
221    * The required visibility of a user's class from a Guice-generated class. Visibility of
222    * package-private members depends on the loading classloader: only if two classes were loaded by
223    * the same classloader can they see each other's package-private members. We need to be careful
224    * when choosing which classloader to use for generated classes. We prefer our bridge classloader,
225    * since it's OSGi-safe and doesn't leak permgen space. But often we cannot due to visibility.
226    */
227   public enum Visibility {
228 
229     /**
230      * Indicates that Guice-generated classes only need to call and override public members of the
231      * target class. These generated classes may be loaded by our bridge classloader.
232      */
233     PUBLIC {
234       @Override
and(Visibility that)235       public Visibility and(Visibility that) {
236         return that;
237       }
238     },
239 
240     /**
241      * Indicates that Guice-generated classes need to call or override package-private members.
242      * These generated classes must be loaded in the same classloader as the target class. They
243      * won't work with OSGi, and won't get garbage collected until the target class' classloader is
244      * garbage collected.
245      */
246     SAME_PACKAGE {
247       @Override
and(Visibility that)248       public Visibility and(Visibility that) {
249         return this;
250       }
251     };
252 
forMember(Member member)253     public static Visibility forMember(Member member) {
254       if ((member.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) == 0) {
255         return SAME_PACKAGE;
256       }
257 
258       Class[] parameterTypes;
259       if (member instanceof Constructor) {
260         parameterTypes = ((Constructor) member).getParameterTypes();
261       } else {
262         Method method = (Method) member;
263         if (forType(method.getReturnType()) == SAME_PACKAGE) {
264           return SAME_PACKAGE;
265         }
266         parameterTypes = method.getParameterTypes();
267       }
268 
269       for (Class<?> type : parameterTypes) {
270         if (forType(type) == SAME_PACKAGE) {
271           return SAME_PACKAGE;
272         }
273       }
274 
275       return PUBLIC;
276     }
277 
forType(Class<?> type)278     public static Visibility forType(Class<?> type) {
279       return (type.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) != 0
280           ? PUBLIC
281           : SAME_PACKAGE;
282     }
283 
and(Visibility that)284     public abstract Visibility and(Visibility that);
285   }
286 
287   /**
288    * Loader for Guice-generated classes. For referenced classes, this delegates to either either the
289    * user's classloader (which is the parent of this classloader) or Guice's class loader.
290    */
291   private static class BridgeClassLoader extends ClassLoader {
292 
BridgeClassLoader()293     BridgeClassLoader() {
294       // use system loader as parent
295     }
296 
BridgeClassLoader(ClassLoader usersClassLoader)297     BridgeClassLoader(ClassLoader usersClassLoader) {
298       super(usersClassLoader);
299     }
300 
loadClass(String name, boolean resolve)301     @Override protected Class<?> loadClass(String name, boolean resolve)
302         throws ClassNotFoundException {
303 
304       if (name.startsWith("sun.reflect")) {
305         // these reflection classes must be loaded from bootstrap class loader
306         return SystemBridgeHolder.SYSTEM_BRIDGE.classicLoadClass(name, resolve);
307       }
308 
309       if (name.startsWith(GUICE_INTERNAL_PACKAGE) || name.startsWith(CGLIB_PACKAGE)) {
310         if (null == GUICE_CLASS_LOADER) {
311           // use special system bridge to load classes from bootstrap class loader
312           return SystemBridgeHolder.SYSTEM_BRIDGE.classicLoadClass(name, resolve);
313         }
314         try {
315           Class<?> clazz = GUICE_CLASS_LOADER.loadClass(name);
316           if (resolve) {
317             resolveClass(clazz);
318           }
319           return clazz;
320         } catch (Throwable e) {
321           // fall-back to classic delegation
322         }
323       }
324 
325       return classicLoadClass(name, resolve);
326     }
327 
328     // make the classic delegating loadClass method visible
classicLoadClass(String name, boolean resolve)329     Class<?> classicLoadClass(String name, boolean resolve)
330       throws ClassNotFoundException {
331       return super.loadClass(name, resolve);
332     }
333   }
334 }
335