JAVA reflection modifies constants and limitations

Source: Internet
Author: User

Problem and a solution

Today, the company's JAVA project encountered a problem: when the xls file is generated, if there is a large amount of data, ArrayIndexOutOfBoundsException may occur.
Google found a BUG in the jxl package used in the item (open-source library used to handle xls files.
We also found a solution: Success. After a try, this method is indeed feasible.

Another solution-Reflection

However, I was reminded by my predecessors that I could give it a try --

Using java reflection, the constant to be modified is forcibly changed to the value we need at runtime.

-- In this way, you do not need to modify the jxl library. It is okay to add a few more words in our project, and the probability of a problem will be much lower.
So I studied it. Although I finally found that this method is not feasible in our project, it is still very rewarding.

First, use reflection to modify Private Static constants for the following Bean classes, where INT_VALUE is a Private Static constant
class Bean{    private static final Integer INT_VALUE = 100;}
Core code for modifying constants:
System. out. println (Bean. INT_VALUE); // obtain the INT_VALUE Field field Field = Bean of the Bean class. class. getField ("INT_VALUE"); // set the field access permission to true: remove the field affected by the private modifier. setAccessible (true);/* remove the effect of the final modifier and set the Field to modifiable */Field modifiersField = Field. class. getDeclaredField ("modifiers"); modifiersField. setAccessible (true); modifiersField. setInt (field, field. getModifiers ()&~ Modifier. FINAL); // set the field value to 200 field. set (null, 200); System. out. println (Bean. INT_VALUE );

The output result of the above Code is:

100
200

It indicates that Private Static constants are successfully reflected.

Restrictions

Note that the static constant type in the above Code is Integer -- but the field type to be modified in our project is not the packaging type Integer, but the basic type int of java.
After changing the constant type to int,

Class Bean {private static final int INT_VALUE = 100; // change the type from Integer to int}

When other code remains unchanged, the output result of the Code turns into a strange one:

100
100

In addition, during the debugging process, we found that during the second output, the Bean in the memory. INT_VALUE is already 200, but System. out. println (Bean. INT_VALUE) but the output result is still an odd 100 ?!

-- Is the reflection invalid?

I tried several other types and found that such seemingly invalid Types will occur on the basic types such as int, long, boolean, and String, if you change the type to the Integer, Long, or Boolean packaging type, or other types such as Date, Object will not be invalid.

Cause

After a series of research, speculation, search, and other processes, we finally found the cause:

For static constants of the basic type, JAVA replaces the reference in this constant in the Code with the corresponding constant value during compilation.

Reference: Modifying final fields in Java
That is, for the constant public static final int maxFormatRecordsIndex = 100, the code

if( index > maxFormatRecordsIndex   ){    index  =  maxFormatRecordsIndex ;}     

This code has been automatically optimized to the following by java during compilation:

if( index > 100){    index = 100;}

So when INT_VALUE is of the int type

System. out. println (Bean. INT_VALUE); // The compilation result is optimized as follows: System. out. println (100 );

Therefore, naturally, no matter how you modify Boolean. INT_VALUE, System. out. println (Bean. INT_VALUE), 100 is still stubbornly output.

-- This is a behavior of JVM optimization code to improve the running efficiency, but it will lead to the illusion that this constant value is not effective when we use reflection. This is probably a limitation of JAVA reflection-it is not too reliable to modify constants of the basic type. Appendix I DEMO code for testing
import java.lang.reflect.Field;import java.lang.reflect.Modifier;import java.util.Date;public class ForClass {    static void setFinalStatic(Field field, Object newValue) throws Exception {        field.setAccessible(true);        Field modifiersField = Field.class.getDeclaredField("modifiers");        modifiersField.setAccessible(true);        modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);        field.set(null, newValue);    }    public static void main(String args[]) throws Exception {        System.out.println(Bean.INT_VALUE);        setFinalStatic(Bean.class.getField("INT_VALUE"), 200);        System.out.println(Bean.INT_VALUE);        System.out.println("------------------");        System.out.println(Bean.STRING_VALUE);        setFinalStatic(Bean.class.getField("STRING_VALUE"), "String_2");        System.out.println(Bean.STRING_VALUE);                System.out.println("------------------");        System.out.println(Bean.BOOLEAN_VALUE);        setFinalStatic(Bean.class.getField("BOOLEAN_VALUE"), true);        System.out.println(Bean.BOOLEAN_VALUE);        System.out.println("------------------");        System.out.println(Bean.OBJECT_VALUE);        setFinalStatic(Bean.class.getField("OBJECT_VALUE"), new Date());        System.out.println(Bean.OBJECT_VALUE);    }}class Bean {    public static final int INT_VALUE = 100;    public static final Boolean BOOLEAN_VALUE = false;    public static final String STRING_VALUE = "String_1";    public static final Object OBJECT_VALUE = "234";}
Code output
100100------------------String_1String_1------------------falsetrue------------------234Fri Apr 25 00:55:05 CST 2014

Description

-- The Boolean and Object type constants are modified correctly, while the changes to the basic types of int and String are "invalid ".

Synchronous publishing in http://www.barryzhang.com/archives/188

Advertise my new blog. Welcome to visit Kazakhstan ~ :BarryZhang.com

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.