When writing a Java framework, it is often necessary to reflect the field of a get or set of a bean, and it is more common to call Java.lang.reflect.Field.get (Object) After the field is fetched, but each time this is called, Can there be room for optimization?
The answer is yes.
First type:
Because each time is a duplicate call, it is thought of caching the field of each bean, but this is not enough, so think of writing a code generator. By generating the code, a get or set each bean directly invokes the bean's getter or setter, and this implementation sounds pretty good, In fact, the use of ASM to generate a class in a classloader loaded in every call directly invoke on it.
Can be simply for a reflex call to do so much, always feel that the cannon hit the mosquito.
The second type:
Thanks to @rednaxelafx's advice, I found a simpler approach: Sun.misc.Unsafe
It is also very simple to use: First get offset from field by Sun.misc.Unsafe.objectFieldOffset (field) and then use Sun.misc.Unsafe.getObject (Object, long) Gets the value of the field on an instance.
The simple test code is as follows:
Import java.io.Serializable; Import Java.lang.reflect.Field; Import Sun.misc.Unsafe; /** * @author Haitao.yao DEC/public class Reflectioncompare {private static final int count = 10000000;/** * @param args */public static void main (string[] args) {Long duration = Testintcommon (); SYSTEM.OUT.PRINTLN ("int common test for" + Count + "times, Duration:" + duration); Duration = Testunsafe (); SYSTEM.OUT.PRINTLN ("int unsafe test for" + Count + "times, Duration:" + duration);} private static Long Testunsafe () {Long start = System.currenttimemillis (); Sun.misc.Unsafe Unsafe = Getunsafe (); int temp = Count; Field field = Getintfield (); Long offset = unsafe.objectfieldoffset (field); while (temp--> 0) {unsafe.getint (New Testbean (), offset);} return System.currenttimemillis ()-Start; private static Long Testintcommon () {Long start = System.currenttimemillis (); int temp = count; Getintfield (). setaccess Ible (TRUE); while (temp--> 0) {testbean bean = new Testbean (); try {Getintfield (). get (bean);} catch (Exception e) {e.printstacktrace ();}} Return System.currenttimemillis ()-Start; private static final Sun.misc.Unsafe Unsafe; static {Sun.misc.Unsafe value = null; try {class<?> clazz = Class.forName ("Sun.misc.Unsafe"); Field field = Clazz.getdeclaredfield ("Theunsafe"); Field.setaccessible (TRUE); Value = (Unsafe) field.get (null); catch (Exception e) {e.printstacktrace (); throw new RuntimeException ("Error to get Theunsafe", e);} unsafe = value; public static final Sun.misc.Unsafe Getunsafe () {return Unsafe;} private static Final Field Intfield; private static final Field Stringfield; static {try {Intfield = TestBean.class.getDeclaredField (' age '); Stringfield = TestBean.class.getDeclaredField ("name") ; catch (Exception e) {e.printstacktrace (); throw new IllegalStateException ("Failed to init testbean field", e);} public static final field Getintfield () {return Intfield.} public static final field Getstringfield () {RETUrn Stringfield; /** * @author Haitao.yao * Dec/Static class Testbean implements serializable{/** * */private static final Long serialversionuid = -5994966479456252766l; private String name; private int age; /** * @return The name/public String GetName () {return name}/** * @param name the name to set/public void Setnam E (String name) {this.name = name}/** * @return The Age */public int getage () {return age;}/** * @param age To set */public void setage (int age) {this.age = age;}} }
Through the test found that the efficiency is ordinary Java.lang.reflect.Field.get (Object) 3 times times, of course, performance of this thing, or test their own assured.
There is a bad place to do this: Sun.misc.Unsafe in Sun's bag, and by default, Eclipse compilation will complain, in window->preference->java->compiler->errors/ warnings->deprecated and restricted API-> forbidden Reference can be modified to warning or ignore. Since unsafe is in use in many of the class libraries in the JDK, the framework code is safe to use, and if API changes are required, the JDK source code changes more than most of us:-0
As for the first method, although the trouble, there is time to try, have time to write.