蹲厕所的熊 转载请注明原创出处,谢谢!
说起对象实例化,想必没有人不知道吧~,最简单的就是使用new关键字来进行实例化对象的操作,首先我们来定义一个对象Person(是它还是它~)
@Data
public class Person {
private int age;
private String name;
}
接下来,我们来把默认的构造函数设置为private,发现不能简单new出一个实例了。
private Person() {}
但是这一步估计也难不住大多数同学,反射不就是用来干这个事的吗?用Person获取到默认的构造函数,设置可访问,最后就可以实例化出Person对象了,so easy~
Constructor<Person> constructor = Person.class.getDeclaredConstructor();
constructor.setAccessible(true);
Person person = constructor.newInstance();
但是反射的前提是得存在构造函数,但是并不是所有的java类都有无参构造函数,并且有的类的构造函数还是private的,更甚有些类是第三方的,我们不能修改源码,这个时候 objenesis
框架就可以发挥它的作用了。我fork出来加了点中文注释,地址:https://github.com/benjaminwhx/objenesis
Objenesis
Objenesis是一个小型java类库用来实例化一个特定class的对象(经过测试有效代码才1538行)。我们先来看看它内部类的继承关系:

Objenesis
内部实现使用策略模式,主要用来提供对象实例化的操作。 ObjenesisBase
是一个基类,内部维护一个由子类提供的策略类 InstantiatorStrategy
,由图中可以看到,策略类主要是 StdInstantiatorStrategy
和 SerializingInstantiatorStrategy
两个。
public class ObjenesisBase implements Objenesis {
protected final InstantiatorStrategy strategy;
protected ConcurrentHashMap<String, ObjectInstantiator<?>> cache;
public ObjenesisBase(InstantiatorStrategy strategy) {
this(strategy, true);
}
public ObjenesisBase(InstantiatorStrategy strategy, boolean useCache) {
this.strategy = strategy;
this.cache = useCache ? new ConcurrentHashMap<String, ObjectInstantiator<?>>() : null;
}
public <T> T newInstance(Class<T> clazz) {
return getInstantiatorOf(clazz).newInstance();
}
@SuppressWarnings("unchecked")
public <T> ObjectInstantiator<T> getInstantiatorOf(Class<T> clazz) {
// 基本类型抛异常
if(clazz.isPrimitive()) {
throw new IllegalArgumentException("Primitive types can't be instantiated in Java");
}
if(cache == null) {
return strategy.newInstantiatorOf(clazz);
}
ObjectInstantiator<?> instantiator = cache.get(clazz.getName());
if(instantiator == null) {
ObjectInstantiator<?> newInstantiator = strategy.newInstantiatorOf(clazz);
instantiator = cache.putIfAbsent(clazz.getName(), newInstantiator);
if(instantiator == null) {
instantiator = newInstantiator;
}
}
return (ObjectInstantiator<T>) instantiator;
}
}
它主要就是通过子类提供的策略类来调用 newInstantiatorOf
方法得到实例化器,最后通过实例化器的 newInstance
方法进行实例化操作。
Objenesis
的主要实现有两个,一个是 ObjenesisStd
和 ObjenesisSerializer
。
ObjenesisStd
是实例化的标准方式,内部使用 StdInstantiatorStrategy
策略类来提供实例化帮助。
public ObjenesisStd() {
super(new StdInstantiatorStrategy());
}
ObjenesisSerializer
是实例化的另外一种方式,内部使用 SerializingInstantiatorStrategy
策略类来提供实例化帮助。
public ObjenesisSerializer() {
super(new SerializingInstantiatorStrategy());
}
InstantiatorStrategy
策略类最终会通过不同的策略来路由不同实现类,我们来看看标准策略类 StdInstantiatorStrategy
:
public class StdInstantiatorStrategy extends BaseInstantiatorStrategy {
public <T> ObjectInstantiator<T> newInstantiatorOf(Class<T> type) {
// HOTSPOT 或者 OPENJDK
if (PlatformDescription.isThisJVM(HOTSPOT) || PlatformDescription.isThisJVM(OPENJDK)) {
// Java 7 GAE was under a security manager so we use a degraded system
if (PlatformDescription.isGoogleAppEngine() && PlatformDescription.SPECIFICATION_VERSION.equals("1.7")) {
if (Serializable.class.isAssignableFrom(type)) {
// 返回序列化实例化器
return new ObjectInputStreamInstantiator<T>(type);
}
// 反射调用无参构造函数来实例化
return new AccessibleInstantiator<T>(type);
}
// UnsafeFactoryInstantiator也可以工作,但是根据测试比Sun的ReflectionFactory慢了2.5倍,所以我更喜欢用它
return new SunReflectionFactoryInstantiator<T>(type);
} else if (PlatformDescription.isThisJVM(DALVIK)) { // 安卓
if (PlatformDescription.isAndroidOpenJDK()) {
// Starting at Android N which is based on OpenJDK
return new UnsafeFactoryInstantiator<T>(type);
}
if (ANDROID_VERSION <= 10) {
// Android 2.3 Gingerbread and lower
return new Android10Instantiator<T>(type);
}
if (ANDROID_VERSION <= 17) {
// Android 3.0 Honeycomb to 4.2 Jelly Bean
return new Android17Instantiator<T>(type);
}
// Android 4.3 until Android N
return new Android18Instantiator<T>(type);
} else if (PlatformDescription.isThisJVM(JROCKIT)) {
// JROCKIT JVM
return new SunReflectionFactoryInstantiator<T>(type);
} else if (PlatformDescription.isThisJVM(GNU)) {
return new GCJInstantiator<T>(type);
} else if (PlatformDescription.isThisJVM(PERC)) {
return new PercInstantiator<T>(type);
}
// Fallback instantiator, should work with most modern JVM
return new UnsafeFactoryInstantiator<T>(type);
}
}
大多数人应该都是跑在 HotSpot
或者 OpenJDK
上的,所以最终会选择 SunReflectionFactoryInstantiator
类,而针对安卓会选择另外的方式,其他虚拟机也有对应的类来实现。
ObjectInstantiator
Objenisis包含很多平台和jvm的实现,看源码的包结构可以分为:
android:Dalvik/Android平台的虚拟机的实例化方式。
basic:基本的实例化方式,有前面提到过的反射,还有序列化、Proxy方式。
gcj:GCJ编译器的实例化方式。
perc:Aonix PERC虚拟机的实例化方式。
sun:sun包下的一些黑科技。
这里我们只关心sun的jvm中的Instantiator的黑科技实现。其中的实现大约有三种:
SunReflectionFactoryInstantiator:使用
sun.reflect.ReflectionFactory
来创建对象。SunReflectionFactorySerializationInstantiator:也是使用
sun.reflect.ReflectionFactory
来创建对象,但是为了兼容序列化,需要找到第一个没有实现serializable接口的父类,性能有一定的损耗。UnsafeFactoryInstantiator:使用
sun.misc.Unsafe.allocateInstance
来创建对象。
还有一种MagicInstantiator看上去没什么用。看作者的测试更推荐使用 SunReflectionFactoryInstantiator
类来实例化对象。
SunReflectionFactoryInstantiator
@Instantiator(Typology.STANDARD)
public class SunReflectionFactoryInstantiator<T> implements ObjectInstantiator<T> {
private final Constructor<T> mungedConstructor;
public SunReflectionFactoryInstantiator(Class<T> type) {
Constructor<Object> javaLangObjectConstructor = getJavaLangObjectConstructor();
// 这个函数是关键,主要是为这个class创建了一个新的constractor
mungedConstructor = SunReflectionFactoryHelper.newConstructorForSerialization(
type, javaLangObjectConstructor);
mungedConstructor.setAccessible(true);
}
// 创建对象
public T newInstance() {
try {
return mungedConstructor.newInstance((Object[]) null);
} catch (Exception e) {
throw new ObjenesisException(e);
}
}
// //获得object的对象的构造函数
private static Constructor<Object> getJavaLangObjectConstructor() {
try {
return Object.class.getConstructor((Class[]) null);
} catch (NoSuchMethodException e) {
throw new ObjenesisException(e);
}
}
}
最关键的还是 newConstructorForSerialization
这个方法(代码太长,缩减了一点代码)
class SunReflectionFactoryHelper {
public static <T> Constructor<T> newConstructorForSerialization(Class<T> type,
Constructor<?> constructor) {
Class<?> reflectionFactoryClass = getReflectionFactoryClass();
// 实例化ReflectionFactory类
Object reflectionFactory = createReflectionFactory(reflectionFactoryClass);
// 获取ReflectionFactory的newConstructorForSerialization方法
Method newConstructorForSerializationMethod = getNewConstructorForSerializationMethod(
reflectionFactoryClass);
// 调用newConstructorForSerialization获得一个被改写的构造函数
return (Constructor<T>) newConstructorForSerializationMethod.invoke(
reflectionFactory, type, constructor);
}
private static Class<?> getReflectionFactoryClass() {
return Class.forName("sun.reflect.ReflectionFactory");
}
private static Object createReflectionFactory(Class<?> reflectionFactoryClass) {
Method method = reflectionFactoryClass.getDeclaredMethod(
"getReflectionFactory");
}
private static Method getNewConstructorForSerializationMethod(Class<?> reflectionFactoryClass) {
return reflectionFactoryClass.getDeclaredMethod(
"newConstructorForSerialization", Class.class, Constructor.class);
}
}
注释写的很清楚,关键就在于 sun.reflect.ReflectionFactory
的 newConstructorForSerialization
方法,这个方法返回的是一个无参的constructor对象,但是绝对不会与原来的constructor冲突,被称为munged 构造函数。
仿照它尝试实例化之前Person类(去掉默认的构造函数)
@Data
public class Person {
private int age;
private String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
}
public static void main(String[] args) throws Exception {
ObjectInstantiator<Person> objectInstantiator = new SunReflectionFactoryInstantiator<>(Person.class);
Person person = objectInstantiator.newInstance();
}
反射操作比较耗时,这里可以提个代码给作者优化一下~
SunReflectionFactorySerializationInstantiator
public class SunReflectionFactorySerializationInstantiator<T> implements ObjectInstantiator<T> {
private final Constructor<T> mungedConstructor;
public SunReflectionFactorySerializationInstantiator(Class<T> type) {
// 返回指定类的第一个非序列化的父类(包括自己)
Class<? super T> nonSerializableAncestor = SerializationInstantiatorHelper
.getNonSerializableSuperClass(type);
Constructor<? super T> nonSerializableAncestorConstructor;
try {
// 获得无参构造函数(该类必须有无参构造函数)
nonSerializableAncestorConstructor = nonSerializableAncestor
.getDeclaredConstructor((Class[]) null);
}
catch(NoSuchMethodException e) {
throw new ObjenesisException(new NotSerializableException(type+" has no suitable superclass constructor"));
}
//获得munged构造函数对象,这个构造函数中会调用nonSerializableAncestorConstructor
mungedConstructor = SunReflectionFactoryHelper.newConstructorForSerialization(
type, nonSerializableAncestorConstructor);
mungedConstructor.setAccessible(true);
}
public T newInstance() {
try {
return mungedConstructor.newInstance((Object[]) null);
}
catch(Exception e) {
throw new ObjenesisException(e);
}
}
}
它从指定类往父类一直找,返回第一个没有实现序列化的类,但是这个类必须要有无参的构造函数,接着还是和和刚才一样,调用 sun.reflect.ReflectionFactory
的 newConstructorForSerialization
方法。
为了印证猜想,让Person类实现了序列化,并继承了一个类 Animal
@Data
public class Person extends Animal implements Serializable {
private int age;
private String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
}
@Data
public class Animal {
String animalName;
public Animal() {
System.out.println("print animal constructor");
}
}
把实例化器换一下,输出结果果然打印了 printanimal constructor
UnsafeFactoryInstantiator
public class UnsafeFactoryInstantiator<T> implements ObjectInstantiator<T> {
private final Unsafe unsafe;
private final Class<T> type;
public UnsafeFactoryInstantiator(Class<T> type) {
this.unsafe = UnsafeUtils.getUnsafe();
this.type = type;
}
public T newInstance() {
try {
// 使用unsafe的allocateInstance实例化对象
return type.cast(unsafe.allocateInstance(type));
} catch (InstantiationException e) {
throw new ObjenesisException(e);
}
}
}
代码很简单,使用了 Unsafe
类的 allocateInstance
方法。
如果读完觉得有收获的话,欢迎点赞、关注、加公众号【蹲厕所的熊】,查阅更多精彩历史!!!




