The JVM executes objects that are very familiar with class files, we are also known as class files, and the JVM specification defines this compiled code file (although not the actual file as mandatory) is very detailed, but we only talk about some macro content, and then have the opportunity to study the details of the content. The format of the class file required by the JVM is a binary format unrelated to the hardware and operating system. It precisely defines the representation of a class or interface, and it even contains details such as byte order, while byte order is generally fixed in the target file format of a particular platform and is not explained.
The data types supported by the JVM are almost the same as defined in the Java language Specification, please note that is almost the same! That is, the original type and reference type, they can be stored in the variable table, can be passed as parameters, is returned by the method, and more often become the object of the operation. Why is it not exactly the same as defined in the Java language Specification? Because there is a primitive type in the JVM that the Java language does not have: the return address type (returnaddress type). The type is a JSR, a ret, and a jsr_w instruction that needs to be used, and its value is a pointer to the opcode of the JVM instruction, and its value cannot be modified by a running program.
Another reference to the Boolean-type value is that it is a completely separate value in the Java language, but only limited support is provided in the JVM, as shown in:
There is no separate operation for Boolean-type directives, and Boolean-type operations in the source code are manipulated as values of type int after compilation.
A Boolean array is directly supported by the JVM, and the newarray instruction can create a Boolean array, and its access and modification operations are performed using an operation instruction of a byte-type array: Baload,bastore. (in jdk1.0,1,1 and 1.2, the Boolean array is encoded as a byte array, each element is 8 bits)
The JVM uses 1 for true, and 0 for false, the compiler maps the Boolean type in the source code to the type int in the JVM, and must be consistent with the requirements of the JVM.
In addition, there is a large section of the JVM specification for floating-point type data, and I don't see much of it, primarily to discuss the relationship between the floating-point type of the JVM and IEEE 754.
Another thing to mention about types is type checking. The JVM expects almost all type checking to be done before it is run (usually by the compiler) without the JVM checking itself out. Values of the original type do not need to be marked or checked at run time to determine their type. They also do not have to differentiate with reference type values, which distinguishes work from the JVM's instruction set, and the JVM's instruction set uses different directives to differentiate between the types of values it is manipulating, such as Iadd, Ladd, Fadd and Dadd are all JVM directives used to add two numbers and produce numeric type results, but each instruction is specific to a particular type, corresponding to int, long, float, and double.
The JVM contains explicit support for objects. A class is a dynamically assigned class instance or an array, and a reference type in the JVM is a reference to an object, and the value of the reference type can be imagined as a pointer to an object, and an object may have multiple references to it, and the object is always manipulated, passed, or tested by reference.
For reference types, the point to mention is NULL, which initially has no run-time type, but it can be converted to any type, and the NULL,JVM does not require any specific value to correspond to it.
With that in mind, we begin to get to the part I want to learn most about when I'm learning the JVM.
The JVM defines several data areas for running a program, including: PC registers, JVM stacks, heaps, method areas, run frequent pools (Runtime Constant pool), and native method stacks (Native methods Stacks), these data areas can be divided into two types depending on their lifetime, one is the same as the JVM's lifetime (both the heap and the method area), one with the same lifetime as the thread (others), and the same data area as the JVM lifetime is created when the JVM is started and destroyed when the JVM exits. Data areas that are the same as the thread lifetimes are one per thread, created when the threads are created, and destroyed when the thread is destroyed.
Since the JVM can support running multiple threads at the same time, each thread necessarily needs its own PC (program counter) register, and each JVM thread can only execute one method at a time, which is the current method of the thread, if the method is not a native method , the PC register holds the address of the current instruction (the JVM's instruction), and if the current method is a native method, the value of the PC register is not defined. The JVM's PC registers are large enough to hold a returnaddress type or a native pointer to a particular platform.
Each JVM thread also has a private JVM stack, which stores frames (as the next article will refer to). The JVM stack is similar to a stack in a traditional programming language like C, which holds local variables and partial results, and also holds some responsibilities in method invocation and return. Because the JVM stack cannot be directly manipulated except for the push and eject of frames, the frames may be allocated on the heap. If the JVM stack required for calculation in one thread is larger than the allowable size, the JVM throws a stackoverflowerror error if the JVM stack is dynamically scalable and if it needs to be expanded, but not enough memory is available or there is not enough memory to create the JVM stack for a new thread, The JVM throws a outofmemoryerror error.
The JVM has only one heap that is shared by all threads, and all class instances and arrays are created in the heap. The objects stored by the heap are reclaimed by an automated storage management system (known as the Garbage Collector (GC)). Objects cannot be explicitly released, and the JVM assumes that there are no specific types of automated storage management systems, and that storage management techniques can be selected based on the system requirements of the implementing person. The JVM throws a outofmemoryerror error if the calculated memory heap is larger than the size that the automatic storage management system can use.
The JVM has only one method area shared by all threads, a method area that resembles a compiled code store for a traditional language, or a "text" segment of a UNIX process. It stores class structures, such as running a constant pool, member and method data, and the code for methods, construction methods, including specific methods for initializing classes and instances, and interface type initialization (which these specific methods will refer to later)). Although the method area is logically part of the heap, a simple implementation of the JVM can choose not to garbage collect or compress the method area (the author's understanding is that the class cannot be unloaded). The JVM specification for the latest version (second edition) does not require the location of the method area or the policy for managing compiled code. If the method area's memory does not meet an allocation request, the JVM throws a outofmemoryerror.
A run-time pool is a run-time representation of a constant pool table in a class file that contains several constants, ranging from a known numeric constant at compile time to a method and member reference that must be parsed at run time. The function of running a constant pool is similar to the symbol table in a traditional programming language, but it contains more data than a typical symbol table.
Each run-time pool is allocated from the JVM's method area, and the Run-time constant pool for a particular method or interface is created by the JVM when creating a class or interface.
When creating a class or interface, the JVM throws a outofmemoryerror if the memory needed to create a run-time pool is more memory than what is available in the method area.
More information about Chang creation may be explained in more detail later.
Implementations of the JVM may use traditional stacks (and more commonly, c stacks) to support native methods (not methods written in the Java language), and native method stacks can also be used to implement parsers for JVM instruction sets in languages such as C. For JVM implementations that cannot load native methods and do not rely on traditional stacks themselves, it can provide no native method stack, and, if provided, the native method stack is usually allocated for each thread when the thread is created (the author's understanding should be a thread that needs to use native methods). If the thread calculates the required memory that is larger than the native method stack allows, the JVM throws a stackoverflowerror error, if the native method stack is dynamically scalable, if there is not enough memory when it needs to be extended, or if there is not enough content to create a native method stack, The JVM throws OutOfMemoryError.
For these data areas above, the JVM specification allows them to be of a fixed size, or it can be dynamically scaled according to the needs of the calculation, and if it is a fixed size, its dimensions can be selected at the time of creation. The implementation of the JVM can give programmers or users the means to control the initial size of the JVM stack, and, in the case of dynamic scaling, can control the maximum size and minimum size, and the memory space they use can be not contiguous.