What is a JVM

Java Virtual Machine (JVM), a Virtual Machine capable of running bytecodes, interpreting bytecodes as Machine instructions in different OS, with the JVM, the Java language runs on different platforms without recompilation, i.e. platform independence.

How it works: Compiled Java program instructions are not executed directly on the hardware system’s CPU, but are executed by the JVM. The JVM shields platform-specific information so that Java language compilers only need to generate the target bytecode (.class) to run on the JVM, meeting the portability, transportability, precompilation, and other requirements of high-level languages.

1. Take Java as an example. We write the Java code in the text compiler and hand it to the "compiler" to compile it into Java Bytecode. The Bytecode is then executed by the JVM, which acts as the "interpreter" and returns the result while interpreting the Bytecode into Machine Code. BASIC, for example, was an early language that could be translated literally by computers. Written by a text compiler, it could be interpreted and executed by the operating system without having to "compile" it. 3, take C language as an example, we write the source code in the text compiler, and then run GCC hello. C to compile the hello.out file, which is composed of a series of machine instructions machine code, can be directly handed over to the hardware to execute.

1.2 JVM startup process

jvm.cfg

-server KNOWN

-client IGNORE

-hotspot ALIASED_TO -server

-classic WARN

-native ERROR

-green ERROR

KNOWN: exists, IGNORE: does not exist, ALIASED_TO: gives another JVM an alias WARN: finds an alternative if it does not exist, and ERROR: does not throw an exception

1.3 Advantage of JVM, other languages choose to implement in JVM

There are many languages that use JVMS, such as Scala, Kotlin, Ceylon, Xtend, Groovy, Clojure; The JVM has matured and matured over time. A complete language includes a front end, optimization, back end, runtime, libraries and the JVM does all the last four.

  • Cross-platform is very economical. The language compiler only needs to output the JVM bytecode. Cross-platform is a lot of work, for example, just developing and generating native code alone requires a lot of effort to optimize for different platforms and processors.
  • The JVM’s superior JIT (Just-in-time compilation) performance. JIT can record the characteristics of a program as it runs and make a lot of optimizations based on them (which is a large part of the excellent performance of Java enterprise applications). JIT Since HotSpot JVM was released with Java 1.2, JVM JIts have continued to improve in performance and are an undisputed success. Having the JVM as the target platform means that a significant amount of performance tuning can be “outsourced” to the JVM, significantly reducing the Guest language development budget.
  • There are already several mature examples and plenty of experience to draw on
  • As a mature, high-level runtime environment, the JVM provides many of the runtime services required by the Guest language, such as memory management (with industry-leading garbage collection, etc.), largely avoiding additional independent development.
  • There are multiple independent implementations of the JVM, and several vendors are working on it, and the data is there, and the community is huge.
  • The Java community has a large number of mature libraries, and generally other languages running on the JVM design a dedicated “bridge” to help libraries that use Java directly, which is a great selling point for potential customers.
  • Java has decent development tools and environments. Many languages that target the JVM consider implementing them in the Java language (at least during the Bootstrap phase).

2. JVM structure

The Java Virtual Machine specification defines a number of subsystems, memory areas, data types, and usage guidelines. These components constitute the internal structure of the Java virtual machine. They not only provide a clear internal structure for the implementation of the Java virtual machine, but also strictly define the external behavior of the implementation of the Java virtual machine.

Here’s a brief description of what each component does

  • Class loader subsystem: Each Java VIRTUAL machine is provided by a class loader subsystem that takes care of the types (classes and interfaces) within the program and assigns them unique names. Each Java virtual machine has an execution engine that executes the instructions contained in the loaded class.

  • Execution of a program requires a certain amount of memory, such as bytecode, additional information about the class being loaded, objects in the program, method parameters, return values, local variables, intermediate variables for processing, and so on. The Java virtual machine stores all this information in data areas. Although every Java virtual machine implementation contains data extents, the Java Virtual Machine specification is very abstract about data extents. Many of the structural details are left to the Java virtual machine implementers. Memory structures on different Java virtual machine implementations vary greatly. Some implementations may take up a lot of memory, while others may take up little memory; Some implementations may use virtual memory, while others do not. This relatively refined Java virtual machine memory specification enables Java virtual machines to be implemented on a wide range of platforms.

  • Some parts of the data area are common to the entire program, while others are controlled by individual threads. Each Java virtual machine contains method areas and heap, which are shared by the entire program. After the Java virtual machine loads and parses a class, it saves the parsed information from the class file in the method area. Objects created during program execution are kept in the heap. When a thread is created, it is assigned its own PC register (program counter) and Java Stack. The PC register holds the next instruction to be executed by the thread when the thread does not use the local method. The Java stack holds the state of a thread when it calls a method, including local variables, parameters to the calling method, return values, and intermediate variables to process. The state when a local method is called is stored in native Method stacks, possibly in registers or other non-platform independent memory.

  • The Java stack consists of stack frames (or frames). The stack block contains the state of the Java method call. When a thread calls a method, the Java virtual machine pushes a new block onto the Java stack, and when the method is finished, the Java virtual machine ejects the corresponding block and throws it away.

  • Instead of using registers to hold the intermediate results of a computation, the Java virtual machine uses a Java stack to hold the intermediate results. This makes the Java virtual machine’s instructions more compact and makes it easier to implement the Java Virtual machine on a registerless device.

2.1 interpreter

An interpreter can be understood as a program that converts one high-level language into another. In the JVM, the interpreter converts bytecode files into machine binary language that our computers can execute directly. However, because every time you run a program, you have to switch to another language before you run it, the interpreter is expected to run very fast, which contributes to the impression that Java is slow.

In essence, each program is a “description” of a machine, and the interpreter “simulates” the operation of the machine, that is, performs “calculations.” So in a sense, the interpreter is the essence of computing

Interpreters are generally “recursive programs.” Recursive because the data structures it deals with (programs) are themselves “recursively defined” structures.

After Java 1.2, HotSpot VM is now built with not only an interpreter but also an advanced JIT (Just In Time Compiler) Compiler, enabling the interpreter and just-in-time Compiler to complement each other while the Java VIRTUAL machine is running

2.2, JIT

The HotSpot virtual machine uses hot code detection technology, which uses a counter to find the code that is most valuable to compile and tells the JIT to compile it on a method basis. If the method is called frequently, standard compilation is triggered; If there are a lot of loops in the method, trigger the on-stack replacement compile action. HotSpot doesn’t have to wait for native code to be output before it can execute a program, reducing the just-in-time compilation pressure and enabling more code optimization techniques. Output high quality OS native code.

Why does the HotSpot VIRTUAL machine use an interpreter and compiler architecture?

Although not all Java virtual machines have an interpreter and compiler architecture, many mainstream commercial virtual machines, such as HotSpot, contain both. The interpreter and the compiler each have their own advantages: when a program needs to be started and executed quickly, the interpreter can be used first, saving compilation time and executing immediately. After the program runs, as time goes by, the compiler gradually comes into play, and more and more code is compiled into local code, which can achieve higher execution efficiency. When the program is running in an environment where memory resources are limited (such as some embedded systems), the interpreter execution can be used to save memory, whereas the compiler execution can be used to improve efficiency. In addition, if a “rare trap” occurs after compilation, you can fall back to explain execution through reverse optimization.

Compilation time overhead

The interpreter’s execution, abstractly, looks like this:

Input code -> [interpreter interprets execution] -> execution results

To JIT compile and then execute, abstractly:

Input code -> [compiler compilation] -> compiled code -> [execution] -> execution result

When we say JIT is faster than interpret, we mean that executing compiled code is faster than the interpreter interprets it, not that compiling is faster than interpreting. JIT compilation, however fast, is at least a little slower than interpreted execution, which requires another “execute compiled code” process to get the final result. Therefore, interpreted execution is always faster than JIT compiled execution for “once” code. What is “code that only executes once”? Roughly speaking, it is strictly “execute once” when both of the following conditions are met

Is called only once, such as the class initializer ().

2. No loops

JIT compilation and then execution of code that only executes once is not worth the cost. For code that is executed only a few times, the speed gain from JIT compilation may not offset the overhead of initial compilation.

JIT compilation guarantees positive benefits only for code that executes frequently. Space overhead for compilation It is normal for the average Java method to have a 10x expansion ratio for the size of the compiled code relative to the size of the bytecode. As with the time overhead mentioned above, the space overhead is also worth compiling only for code that executes frequently, and compiling all code significantly increases the amount of space it takes up, leading to “code explosion.” This explains why some JVMS choose not to always do JIT compilation, opting instead for a hybrid execution engine with an interpreter +JIT compiler.

Why does the HotSpot VIRTUAL machine implement two different just-in-time compilers?

Two just-in-time compilers are built into the HotSpot VIRTUAL machine: Client Complier and Server Complier (C1 and C2 compilers for short) for the Client and Server side respectively. The current HotSpot virtual machine defaults to an interpreter working directly with one of the compilers. Which compiler the program uses depends on the mode in which the virtual machine is running. The HotSpot virtual machine automatically selects a running mode based on its own version and the hardware capabilities of the host machine.

Use Client Complier for higher compilation speed and Server Complier for better compilation quality. The reason why multiple just-in-time compilers are provided is similar to the reason why multiple garbage collectors are provided is to accommodate different application scenarios.

Developers can explicitly specify which just-in-time compiler to use for the Java virtual machine at run time by using the following command:

-client: specifies that the Java VM runs in client mode and uses the C1 compiler. -server: specifies that the Java VM runs in server mode and uses the C2 compiler.Copy the code

Summarize the JVM products https://en.wikipedia.org/wiki/Comparison_of_Java_virtual_machines wiki

3. View bytecode files through jclasslib

Bytecode escape makes it easy to see how init and Add methods are loaded.

Iload_1 loads int values from local variable 0. Iload_2 loads int values from local variable 0. Iadd performs int additionCopy the code

1, [discussion] [HotSpot VM] JIT compilation and execution of native http://hllvm.group.iteye.com/group/topic/39806

2, the JVM http://blog.csdn.net/tingfeng96/article/details/52261219 compiler process

3, the JVM instant compiler (JIT) http://blog.csdn.net/sunxianghuang/article/details/52094859