Talk about serialization (ii) Use Sun.misc.Unsafe to bypass the new mechanism to create Java objects

Source: Internet
Author: User
Tags serialization

One common problem in a serialized problem domain is how to create a Java object when deserializing, because the goal of deserialization is to convert a binary stream into an object.

There are several ways to create objects in Java:

1. Explicitly call the new statement, such as DemoClass demo = new DemoClass ()

2. Using the reflection mechanism, the newinstance () method of the class object, such as DemoClass demo = DemoClass.class.newInstance (). But there's a premise that you have to provide an argument-free constructor.

3. Use the reflection mechanism to create objects using constructor objects

These three methods are essentially the same, both explicit and implicit, as the new mechanism of the regular Java-created object. A new operation, compiled into instructions, is 3.

The first instruction means allocating a chunk of memory based on the type

The second instruction is to press the memory address returned by the first instruction into the top of the operand stack.

The third instruction is the constructor of the calling class


One of the problems with the new mechanism is:. You must use this parameter constructor when the class only provides a constructor that has a parameter.

So the problem is that when deserializing, it is not possible to use the display ground new operation, because it is dynamically called according to the type of the pass-through. The use of newinstance must be out of the doubt, because it is not possible to determine whether this class provides a parameterless constructor. Only the third, using the reflection mechanism, uses the constructor object to create the object.

However, the Consturctor object has a constraint, which is to provide a list of the types of parameters, and then use the Constructor.newinstance method to pass the corresponding number of arguments.

In deserialization this scenario, you can do this by first obtaining a list of constructor parameter types based on reflection, and then constructing a list of corresponding default values for each type, and then calling the Constructor.newinstance () method. This allows you to create an object with a default value.

But the problem comes again, in case the constructor of this class does something special, such as judging the value of the passed parameter, if the parameter value does not conform to the specification and throws an exception, then the creation of the object fails.

public static void TestConstructor () {try {class[] cls = new class[] {int.class, int.class};        Constructor C = DemoClass.class.getDeclaredConstructor (CLS);D emoclass obj = (DemoClass) c.newinstance (0, 0); System.out.println (Obj.getvalue1 ()); System.out.println (Obj.getvalue2 ());} catch (Exception e) {e.printstacktrace ();}} public static void Testconstructorwityparametertypes () {try {constructor[] c = DemoClass.class.getDeclaredConstructors (); type[] parametertypes = C[0].getgenericparametertypes ();//determine type, set default value DemoClass obj = (DemoClass) c[0]. Newinstance (0, 0); System.out.println (Obj.getvalue1 ()); System.out.println (Obj.getvalue2 ());} catch (Exception e) {e.printstacktrace ();}}

So some serialization protocols require that a serialized object must provide an argument-free constructor, you can call the parameterless constructor when deserializing.


Here is an issue that uses the Sun.misc.Unsafe method to solve the problem of creating a Java object due to a parametric constructor. Unsafe has a allocateinstance (Class) method, this method only need to pass in a type can create Java object, not just perfect solve our problem?

The new operation is parsed into 3 steps, and the Unsafe.allocateinstance () method value does the first and second steps, allocating memory space, returning the memory address, and not making a third call to the constructor. So the object created by the Unsafe.allocateinstance () method is only the initial value, there is no default value, and no value is set by the constructor, because it completely does not use the new mechanism to directly manipulate memory to create the object. Here's a complete example, including how to get an unsafe object.

Referencing the Sun.misc.Unsafe class in eclipse needs to be set up Preference----------and Compiler--- errors/warnings Forbidden Reference, change from error to warning

Package Com.zc.lock;import Java.lang.reflect.field;import Sun.misc.unsafe;public class Unsafeutility {private static Unsafe unsafe;static {try {Field F = Unsafe.class.getDeclaredField ("Theunsafe"); F.setaccessible (true); unsafe = (unsafe ) f.get (null);} catch (Exception e) {}}public static unsafe getunsafe () {return unsafe;}}

A test case

Package Com.zc.lock.test;public class DemoClass {private int value1;private int value2 = 10;public DemoClass (int value1, I NT value2) {this.value1 = value1; this.value2 = value2;} public int getValue1 () {return value1;} public void setValue1 (int value1) {this.value1 = value1;} public int getValue2 () {return value2;} public void setValue2 (int value2) {this.value2 = value2;}} Package Com.zc.lock.test;import Java.lang.reflect.constructor;import Java.lang.reflect.type;import Sun.misc.Unsafe Import Com.zc.lock.unsafeutility;public class main {    public static void Main (string[] args) {//         testnewobject ();//        testnewinstance ();//         testconstructor ();//         Testconstructorwityparametertypes ();//        testunsafeallocateinstance ();     }        public static void TestunsafeaLlocateinstance () {        unsafe Unsafe = Unsafeutility.getunsafe ();                try {             democlass obj = (DemoClass) unsafe.allocateinstance (democlass.class);            system.out.println (obj.getvalue1 ());            system.out.println (Obj.getvalue2 ());            obj.setvalue1 ( 1);            obj.setvalue2 (2);             system.out.println (obj.getvalue1 ());             System.out.println (Obj.getvalue2 ());        } catch (Instantiationexception e) {             e.printstacktrace ();        }    }        public static void Testnewobject () {         democlass obj = new DemoClass;         System.out.println (Obj.getvalue1 ());        system.out.println (Obj.getvalue2 ());     }        public static void Testnewinstance () {         try {            democlass obj = DemoClass.class.newInstance ();            system.out.println ( Obj.getvalue1 ());            system.out.println (Obj.getvalue2 ());         } catch (Instantiationexception e) {             e.printstacktrace ();        } catch (Illegalaccessexception e) {             e.printstacktrace ();        }     }        public static void TestConstructor () {        try  {            class[] cls = new class[] {int.class, Int.class};            Constructor C = DemoClass.class.getDeclaredConstructor (CLS);             democlass obj = (DemoClass) c.newinstance (0, 0);   & nbsp;        system.out.println (obj.getvalue1 ());            system.out.println (Obj.getvalue2 ());        } catch ( Exception e) {            e.printstacktrace ();         }    }        public STAtic void Testconstructorwityparametertypes () {        try {             constructor[] C = DemoClass.class.getDeclaredConstructors ();             type[] parametertypes = c[0].getgenericparametertypes ();             //determine type, set default value              DemoClass obj = (DemoClass) c[0].newinstance (0, 0);             System.out.println (Obj.getvalue1 ());            system.out.println ( Obj.getvalue2 ());        } catch (Exception e) {        & nbsp;   e.printstacktrace ();        }    }    } 






Talk about serialization (ii) Use Sun.misc.Unsafe to bypass the new mechanism to create Java objects

Related Article

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.