Know what it is and why

The foreword 0.

In our last article, Reflection from Beginner to Master: An in-depth look at the Class Class, we took a closer look at the principles behind the Class Class. In this article, we examine the rationale behind the Constructor use method.

1. Constructor

There are two ways to call a constructor through reflection:

  • Calling the no-argument constructor: class.newinstance ()
  • Call the constructor with arguments:
    • Get Constructor from the Class Class
    • Call newInstance(Object… Initarges) method

For details, see Reflection from 0 to Getting Started. Constructor newInstance(Object… Initarges) method.

1.1 newInstance

To understand how this works, the first step is to read the JDK annotations, which look like this:

(Excuse me, I don’t understand this, the end of the play…)

Don’t go. I’ll translate for you.

Using Constructor to represent the Constructor, create and initialize an instance based on the parameters. The parameters are automatically unboxed to match the original formal parameters, and the original and reference parameters must be converted into method calls as needed.

To get a no-argument constructor, the argument length can be 0 or NULL

Call a non-static inner class with the argument… (Not translated here)

Access passes and parameter checks succeed, instantiation continues. If the constructor’s declared class is not initialized, it needs to be

The constructor completes and returns the newly created and initialized instance

Here are a few key takeaways from Xiao Li’s rough translation:

  • The initialization instance is created according to the parameters, and the parameters have matching rules.
  • Gets the no-argument constructor, which can be 0 or NULL;
  • To have access and to check parameters, you need to get the constructor’s declaration class;

With that in mind, let’s read the source code for newInstance(), as shown below:

The source code can be split into three pieces:

  1. Verify permissions: verify permissions is not this analysis, you can view the source code
  2. Gets the declared class of the constructor
  3. Create the entity

Gets the declared class of the constructor

The constructor declares that class ConstructorAccessor is an interface, as shown in the following figure:

See the following structure of the interface implementation class (dotted line represents implementation interface, blue line represents inheritance, so what is the white line?)

As you can see from the figure, the implementation classes inherit the ConstructorAccessorImpl abstract class and implement the newInstance() method.

So which implementation class do we use? Let’s move on

If a ConstructorAccessor has been created, get and assign a value. If not, a ConstructorAccessor is created using the newConstructorAccessor method. The newConstructorAccessor method is as follows:

NewConstructorAccessor is divided into three parts:

  1. Check whether the system is initialized

This is the ReflectionFactory checking the initialization status, and if it is not initialized it will perform the operations circled in red below.

So what do you want to guess about this one?

In the first place, since inflation is literally inflation or inflation, noInflation is also literally non-inflation.

Threshold: An inflationThreshold: an inflationThreshold: an inflationThreshold

According to the literal understanding, noInflation can be used to judge whether inflation is rising. InflationThreshold is a threshold value of inflation.

Ask Baidu to verify our results:

Java Native Interface (JNI) : The Java Native Interface is used to write programs, ensuring that the code can be easily portable on different platforms.

As a close guess, the JVM has two ways to access information about reflected classes, either using a JNI reader or a Java bytecode accessor. InflationThreshold is the number of times the JNI accessor is used. A value of 0 indicates that it is never read from the JNI accessor. If you want to force Java bytecode accessors, set noInflation to true.

The default inflationThreshold value is 15. If inflationThreshold is not modified, JVM access to reflected classes will read information from the JNI accessor 15 times before using the Java bytecode accessor

This explains why there should be an initial detection operation.

A few things to learn from this section:

We can use -d = to set System properties and system.getproperty (” property name “) to getProperty values.

  1. Gets a Class instance of the current Class

  1. Obtain ConstructorAccessor according to the condition

    So many if conditional judgment, don’t panic, I will help you analyze a wave:

    • Step 1 verifies that the Class instance obtained in step 2 is abstract and throws an exception if it is.
    • Second, check if it is a Class instance, because the constructor of a Class instance is private, so this should also throw an exception.
    • Step 3, judge whether the Class instance inheriting ConstructorAccessorImpl, if it is a father-son relationship, call the create ConstructorAccessor BootstrapConstructorAccessorImpl, This method is to call native methods, the underlying c++ implementation of the local interface.
    • Step 4, if noInflation to true and the Class instance is not anonymous, you need to call MethodAccessorGenerator. GenerateConstructor create ConstructorAccessor (), Without going into the details, the principle is to read the binary file, load in an instance of the Class, and then get the desired Constructor based on some criteria.
    • Step 5, the above conditions are not met, call NativeConstructorAccessorImpl, look at the source of the this method:

    If the number of calls is greater than the inflationThreshold (15 by default), check whether the methods invoked are the same as those in the fourth step.

    If the value is less than or equal to the inflationThreshold, we call newInstance0, which is a native method and calls the local interface.

    In fact, the first step of initialization is to prepare for this.

    Here are not done, there is also a DelegatingConstructorAccessorImpl method.

    That this piece USES the proxy pattern, put the NativeConstructorAccessorImpl into DelegatingConstructorAccessorImpl delegate. NewInstance calls the Delegate newInstance method.

    Remember when I first asked what the white line was for? That clears it up.

It’s a little bit too much, so LET me draw a picture to show you:

Image links

Create an instance

The previous step gets the implementation class for ConstructorAccessor and calls the newInstance method directly to create the instance.

2. To summarize

Let’s review what we’ve already done:

According to the JDK, newInstance can be initialized according to parameters and return an instance. To get an instance, we must get the constructor’s declaration class ConstructorAccessor. Then we dig into ConstructorAccessor.

ConstructorAccessor has an abstract class called ConstructorAccessorImpl. The other implementation classes that inherit ConstructorAccessorImpl are the following:

  • InstantiationExceptionConstructorAccessorImpl: to save exception information, call newInstance throws an InstantiationException abnormalities.

  • BootstrapConstructorAccessorImpl: When you need to create instances of the Class and ConstructorAccessorImpl parent-child relationships, will return to BootstrapConstructorAccessorImpl, call is at the bottom of the method, through the c + +.

  • SerializationConstructorAccessorImpl: is an abstract class, read when the JVM from Java bytecode, returns the implementation class.

  • NativeConstructorAccessorImpl: Call the local interface method to create ConstructorAccessor, and compare the number of calls to the inflationThreshold, which is 15 by default. By * * – Dsun. Reflect. InflationThreshold = * * to modify the default values.

    When the number of calls is greater than 15, the JVM fetches Java bytecode. Instead, get it from the local interface.

  • DelegatingConstructorAccessorImpl: the proxy class, is NativeConstructorAccessorImpl parent class.

Get the ConstructorAccessor, and create the instance by calling the newInstance() method.

Reflection related articles

Reflection from Zero to The Beginning

Reflection from Beginner to Master: An in-depth look at the Class Class

Public number: Java knowledge school, there are my recently organized reflection related content, I hope to help you.