com.google.inject.internal.BytecodeGen Maven / Gradle / Ivy
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.inject.internal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.inject.internal.aop.ClassBuilding.buildFastClass;
import static com.google.inject.internal.aop.ClassBuilding.canEnhance;
import static com.google.inject.internal.aop.ClassBuilding.canFastInvoke;
import static com.google.inject.internal.aop.ClassBuilding.signature;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.MapMaker;
import com.google.inject.internal.aop.ClassBuilding;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.BitSet;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function;
/**
* Utility methods for circular proxies, faster reflection, and method interception.
*
* This class makes heavy use of {@link Function} and {@link BiFunction} types when interacting
* with generated fast-classes and enhanced proxies. This is a deliberate design decision to avoid
* using Guice-specific types in the generated classes. This means generated classes can be defined
* in the same {@link ClassLoader} as their host class without needing access to Guice's own {@link
* ClassLoader}. (In other words it removes any need for bridge {@link ClassLoader}s.)
*
* @author [email protected] (Stuart McCulloch)
* @author [email protected] (Jesse Wilson)
*/
public final class BytecodeGen {
private static final Map, Boolean> circularProxyTypeCache =
new MapMaker().weakKeys().makeMap();
/** Returns true if the given object is a circular proxy. */
public static boolean isCircularProxy(Object object) {
return object != null && circularProxyTypeCache.containsKey(object.getClass());
}
/** Creates a new circular proxy for the given type. */
static T newCircularProxy(Class type, InvocationHandler handler) {
Object proxy = Proxy.newProxyInstance(type.getClassLoader(), new Class>[] {type}, handler);
circularProxyTypeCache.put(proxy.getClass(), Boolean.TRUE);
return type.cast(proxy);
}
public static final String ENHANCER_BY_GUICE_MARKER = "$$EnhancerByGuice$$";
public static final String FASTCLASS_BY_GUICE_MARKER = "$$FastClassByGuice$$";
/** Builder of enhanced classes. */
public interface EnhancerBuilder {
/**
* Lists the methods in the host class that can be enhanced.
*
* This always includes public and protected methods that are neither static nor final.
*
*
Package-private methods can only be enhanced if they're in the same package as the host
* and we can define types in the same class loader with Unsafe. The {@link #finalize} method
* can never be enhanced.
*/
Method[] getEnhanceableMethods();
/**
* Generates an enhancer for the selected subset of methods.
*
*
The enhancer maps constructor and method signatures to invokers, where each invoker is
* represented as a {@link BiFunction} that accepts a context object and an argument array.
*
*
Constructor invokers take an array of {@link InvocationHandler}s as their context object.
* This is stored in the enhanced class before the original host class constructor is called,
* with arguments unpacked from the argument array. The enhanced instance is then returned.
*
*
Method invokers take an enhanced instance as their context object and call the original
* super-method with arguments unpacked from the argument array, ie. provides super-invocation.
*/
Function> buildEnhancer(BitSet methodIndices);
}
/** Create a builder of enhancers for the given class. */
static EnhancerBuilder enhancerBuilder(Class> hostClass) {
return ENHANCER_BUILDERS.getUnchecked(hostClass);
}
/**
* Returns an invoker that constructs an enhanced instance. The invoker function accepts an array
* of invocation handlers plus an array of arguments for the original constructor.
*/
static BiFunction