Implementation and performance test of objenesis

Source: Internet
Author: User

Recently see Kryo source found that using a Java library called Objenesis, mainly used to create objects, it can not call the constructor to create the object. Since not all Java classes have parameterless constructors, and the constructors of some classes are private, some of them are third parties, and we can't modify the source code, so this library is still very useful. Http://objenesis.org/details.html

Objenisis contains a lot of platform and JVM implementations, where we only care about the implementation of Instantiator in the Sun's JVM. There are about three implementations: Sunreflectionfactoryinstantiator: Using Sun.reflect.ReflectionFactory to create objects Sunreflectionfactoryserializationinstantiator: You also use Sun.reflect.ReflectionFactory to create objects, but to be compatible with serialization, you need to find the first one that does not implement the serializable interface. Parent class, performance has a certain loss. Unsafefactoryinstantiator: Using Sun.misc.Unsafe.allocateInstance to create objects

There is another kind of magicinstantiator that doesn't seem to work. Sunreflectionfactoryinstantiator

Let's take a look at the implementation of Sunreflectionfactoryinstantiator, the code is very short.

public sunreflectionfactoryinstantiator (class<t> type) {//Get object CONSTRUCTOR&L
      t;object> javalangobjectconstructor = Getjavalangobjectconstructor (); This function is the key, primarily for this class to create a new constractor Mungedconstructor =
      Sunreflectionfactoryhelper.newconstructorforserialization (type, javalangobjectconstructor);
   Mungedconstructor.setaccessible (TRUE);
      //Create object, everyone read understand public T newinstance () {try {return mungedconstructor.newinstance ((object[)) null);
      catch (Exception e) {throw new Objenesisexception (e); }///Get Object private static Constructor<object> Getjavalangobjectconstructor () {try {ret
      Urn Object.class.getConstructor ((class[]) null);
      catch (Nosuchmethodexception e) {throw new Objenesisexception (e); }
   }

From the above code can see the Sunreflectionfactoryhelper.newconstructorforserialization function is the key, let's take a look at this source:

 public static <T> constructor<t> newconstructorforserialization (class<t> type, CONSTRUCTOR&LT;?&G T constructor) {//The following two lines here is mainly to get Sun.reflect.ReflectionFactory object class<?> reflectionfactoryclass = Getrefle
      Ctionfactoryclass ();

    Object reflectionfactory = createreflectionfactory (Reflectionfactoryclass); Method object for obtaining newconstructorforserialization methods Newconstructorforserializationmethod =

Getnewconstructorforserializationmethod (Reflectionfactoryclass); Using reflection to invoke the Newconstructorforserialization method to get a new constructor object try {return (constructor<t>) newconstructo
      Rforserializationmethod.invoke (Reflectionfactory, type, constructor);
      catch (IllegalArgumentException e) {throw new Objenesisexception (e);
      catch (Illegalaccessexception e) {throw new Objenesisexception (e); catch (InvocationTargetException e) {throw new Objenesisexception (e); }
   }

The notes are written very clearly, The key is in the Newconstructorforserialization method of sun.reflect.ReflectionFactory, in fact this method returns a parameterless constructor object, but never conflicts with the original constructor , which is called the Munged constructor. Sunreflectionfactoryserializationinstantiator

Let's take a look at the implementation

public class Sunreflectionfactoryserializationinstantiator<t> implements objectinstantiator<t> {private

   Final constructor<t> Mungedconstructor; 
      Public Sunreflectionfactoryserializationinstantiator (class<t> type) {//Gets the class object of the first class in the parent class that does not implement the Serializable interface class<?

      Super t> Nonserializableancestor = serializationinstantiatorhelper. Getnonserializablesuperclass (type); Get the parameterless constructor constructor<?
      Super T> Nonserializableancestorconstructor;
      try {nonserializableancestorconstructor = Nonserializableancestor. GetConstructor ((class[)) null); catch (Nosuchmethodexception e) {throw new Objenesisexception (new Notserializableexception (type+) ha         
      s no suitable superclass constructor ")); //Get the Munged constructor object, which will call nonserializableancestorconstructor Mungedconstructor = Sunreflectionfactoryhelp Er.newconstructorforserialization (Type, nonseriAlizableancestorconstructor);
   Mungedconstructor.setaccessible (TRUE);
      Public T newinstance () {try {return mungedconstructor.newinstance ((object[)) null);
      catch (Exception e) {throw new Objenesisexception (e); }
   }
}

The code is simple, the only question is serializationinstantiatorhelper.getnonserializablesuperclass (type); Let's look at the implementation.

public static <T> class<? Super t> Getnonserializablesuperclass (class<t> type) {
      class<? Super t> result = type;
      while (the Serializable.class.isAssignableFrom (result)) {result
         = Result.getsuperclass ();
         if (result = = null) {
            throw new Error ("Bad class Hierarchy:no non-serializable parents")
         ;
      }
      return result;

   }

It's actually a loop to find the first class object that does not have a parent class that implements the Serializable interface. Unsafefactoryinstantiator

Implementation code:

private static Unsafe Unsafe;
   Private final class<t> type;

   Public Unsafefactoryinstantiator (class<t> type) {
   //Initialize unsafe object, otherwise cannot be used.
      if (unsafe = = null) {
         Field F;
         try {
            f = Unsafe.class.getDeclaredField ("Theunsafe");
         } catch (Nosuchfieldexception e) {
            throw new Objenesisexception (e);
         }
         F.setaccessible (true);
         try {
            unsafe = (unsafe) f.get (null);
         } catch (Illegalaccessexception e) {
            throw new Objenesisexception (e) ;
         }
      }
      This.type = type;
   }

Creates an object using the Unsafe.allocateinstance method, and then casts it. Public
   T newinstance () {
      try {return
         type.cast (unsafe.allocateinstance (type));
      } catch ( Instantiationexception e) {
         throw new objenesisexception (e);
      }
   }

The code is simple. Performance Test

Objenesis has benchmark, I ran on my Windows computer:

Environment: 12GB Memory Oracle JDK 64-bit 1.8 i5 Windows 8

Results

 Createobject.createobjectwithconstructor (new) AVGT 20 6.122±1.672 ns/op Createo Bject.createobjectwithconstructor (newinstance) avgt 20 7.614±1.672 ns/op Createobject.createo Bjectwithmungedconstructor avgt 20 8.415±0.252 ns/op Createobject.createobjectwithmungedconst Ructorraw avgt 20 10.413±1.187 ns/op createobject.createobjectwithmungedconstructorrawandcast av 
 GT 20 10.644±0.186 ns/op Createobject.createobjectwithunsafe AVGT 20 29.813 ±1.885 ns/op Createobject.createobjectwithunsaferaw avgt 20 26.572±0.261 ns/o P createobject.createobjectwithunsaferawandcast avgt 20 27.153±1.336 ns/op createobject.creat Eobjectwithunsaferawexception avgt 20 27.390±1.090 ns/op 
Mungedconstructor is the fastest, 2ns slower than the new, 1ns slower than the newinstance. Unsafe is very slow, it takes about 3.5 times times the Mungedconstructor, is 5 times Times New, and 4 times times the newinstance.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.