In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-02 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)05/31 Report--
In this article Xiaobian for you to introduce in detail "Java how to look at the Lambda source code", the content is detailed, the steps are clear, the details are handled properly, I hope this "Java how to look at the Lambda source code" article can help you solve your doubts, following the editor's ideas slowly in-depth, let's learn new knowledge together.
1 、 Demo
First, let's look at the Demo of a Lambda expression, as shown in the following figure:
The code is relatively simple, that is, a new thread prints a sentence, but for the code ()-> System.out.println ("lambda is run") in the picture, many students may feel very confused. How does Java identify this kind of code?
If we change it to an anonymous inner class, it will be very clear and everyone can understand it, as shown in the following figure:
Does that mean that code in the form of ()-> System.out.println ("lambda is run") actually creates inner classes? In fact, this is the simplest Lambda expression, we can not see the source code and its underlying structure through IDEA, let's introduce a few ways to see its underlying implementation.
2. Abnormal judgment method
We can actively throw an exception during code execution, print out the stack, and the stack will explain its running trajectory. Generally speaking, this method is simple and efficient, and you can basically see the hidden code in many cases. Let's try it, as shown below:
From the exception stack, we can see that JVM automatically establishes an inner class for the current class (the $in the error stack indicates that there is an inner class). The code of the inner class throws an exception during execution, but the code shown here is Unknown Source, so we cannot debug it. In general, exceptions can expose the path of code execution, and we can hit the breakpoint and run it again. But for Lambda expressions, we only know that there is an inner class through exception judgment, but we can't see the source code in the inner class.
3. Javap command method
Javap is a tool that comes with Java to view class bytecode files. Computers that have installed the basic Java environment can directly execute javap commands, as shown below:
In the command options, we mainly use the command-v-verbose, which can fully output the contents of the bytecode file.
Next, we use the javap command to look at the Lambda.class file, and we will bring some knowledge about the class file in the course of the explanation.
We find the location of Lambda.class in the command window, execute the command: javap-verbose Lambda.class, and then you will see a long list of things called assembly instructions, which we will explain one by one (all the references are from the Java virtual machine specification, not one by one):
We can easily find a long list of types that Constant pool starts with in assembly instructions, we call it constant pool, official English is called Run-Time Constant Pool, we simply understand it as a table full of constants, table contains clear numbers and text at compile time, type information of classes, methods and fields, and so on. Each element in table is called cpinfo,cpinfo, which consists of a unique identification (tag) + name. Currently, there are a total of tag types:
Post some of the pictures we parsed:
The word Constant pool in the figure indicates that the current information is a constant pool.
Each line is a cp_info, and the # 1 in the first column represents the position marked 1 under the constant pool
The second column of each row is the unique identifier (tag) of cp_info. For example, Methodref corresponds to the CONSTANT_Methodref in the above table (value corresponds to 10 tag in the table above), indicating that the current row represents the descriptive information of the method, such as method name, input parameter type, output parameter type, and so on. The specific meaning can be queried in the Java virtual machine specification. The screenshot of Methodref is as follows:
The third column of each row, if it is a specific value, displays the specific value directly. If it is a complex value, it will display a reference to cp_info. For example, in the figure, the reference to red 2, the reference to two cp_info,13 at positions 13 and 14 indicates that the method name is init,14 that the method has no return value, and the combination of the method name and the return type is a no-parameter constructor.
The fourth column of each row is the specific value.
For the more important cp_info types, let's explain what they mean:
InvokeDynamic represents a dynamic calling method, which we will explain in more detail later
Fieldref represents the description of the field, such as the name and type of the field
NameAndType is a description of fields and method types
MethodHandle method handle, a general term for dynamically calling methods. At compile time, we don't know which method it is, but the runtime will definitely know which method is called.
The MethodType dynamic method type, which is known only when running dynamically.
From the three red marks in the above figure, we find that Ljava/lang/invoke/MethodHandles$Lookup,java/lang/invoke/LambdaMetafactory.metafactory code is similar to this. MethodHandles and LambdaMetafactory are both important methods under the java.lang.invoke package. Invoke package mainly implements the functions of dynamic languages. We know that java language is a statically compiled language. At the time of compilation, the types of classes, methods, fields, etc., have been determined, while invoke implements a dynamic language. In other words, you don't know what types of classes, methods, and fields are at compile time, but only at run time.
For example, this line of code: Runnable runnable = ()-> System.out.println ("lambda is run"); when the compiler compiles (), the parenthesis compiler does not know what it is, and only at run time will it know that this represents the Runnable.run () method. Many classes in the invoke package represent these (), which we call the method handle (MethodHandler). When compiling, the compiler only knows that this is a method handle, not what method is actually executed, and it is only known when it is executed, so the question is, when JVM executes, how do you know that () this method handle actually executes the Runnable.run () method?
First, let's take a look at the assembly instructions for the simple method:
You can see from the figure above that the () in the ()-> System.out.println ("lambda is run") code in the simple method is actually the Runnable.run method.
We trace back to the # 2 constant pool, which is marked red 1 in the above figure. InvokeDynamic indicates that this is a dynamic call. The cp_info of the two constant pools is called, and the location is # 0 run pool 37. We look down for # 37 to represent / / run: () Ljava/lang/Runnable, which indicates that the Runnable.run () method needs to be called dynamically when the JVM is actually executed. We can see from the assembly instruction that () is actually Runnable.run (). Let's debug to prove it.
We found the word LambdaMetafactory.metafactory in the above figure 3. By querying the official documents, we know that this method is the key to linking to the real code during execution, so we hit a breakpoint debug in the metafactory method, as shown in the following figure:
The input parameter caller of the metafactory method represents the location where the actual dynamic call occurs. InvokedName represents the name of the calling method, invokedType represents multiple input and output parameters of the call, samMethodType represents the parameters of the specific implementer, implMethod represents the actual implementer, and instantiatedMethodType is equivalent to implMethod.
To sum up the above:
1: from the simple method of the assembly instruction, we can see that the Runnable.run method will be executed
2: in the actual run time, JVM encounters the invokedynamic instruction of the simple method and dynamically calls the LambdaMetafactory.metafactory method to execute the specific Runnable.run method.
So you can attribute the specific execution of the Lambda expression value to the invokedynamic JVM instruction, which makes it possible to find the specific code to be executed at dynamic runtime, even though you don't know what to do at compile time.
Then let's take a look at the end of the assembly instruction output, we found the inner class found in the exception judgment, as shown in the following figure:
There are many arrows in the picture above, and layer by layer expresses all the information of the current inner class.
Read here, this "Java how to look at Lambda source code" article has been introduced, want to master the knowledge of this article also need to practice and use in order to understand, if you want to know more about the article, welcome to pay attention to the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.