📄 overview.doc.html
字号:
An implementation of the Java Virtual Machine may use conventional stacks, colloquially called "C stacks," to support <code>native</code> methods, methods written in languages
other than Java. A native method stack may also be used to implement an emulator
for the Java Virtual Machine's instruction set in a language such as C. Implementations that do not support <code>native</code> methods, and that do not themselves rely on conventional stacks, need not supply native method stacks. If supplied, native method
stacks are typically allocated on a per thread basis when each thread is created.
<p><a name="21801"></a>
The Java Virtual Machine specification permits native method stacks to be of either a fixed or a dynamically varying size. If the native method stacks are of a fixed size, the size of each native method stack may be chosen independently when that stack is created. In any case, a Java Virtual Machine implementation may provide the programmer or the user control over the initial size of the native method stacks. In the case of varying-size native method stacks, it may also make available control over the maximum and minimum method stack sizes.<p>
<a name="23251"></a>
The following exceptional conditions are associated with Java stacks:<p>
<ul><a name="21973"></a>
<li>If the computation in a thread requires a larger native method stack than is permitted, the Java Virtual Machine throws a <code>StackOverflowError</code>.
<a name="23252"></a>
<li>If native method stacks can be dynamically expanded, and native method stack expansion is attempted but insufficient memory can be made available, or if insufficient memory can be made available to create the initial native method stack for a new thread, the Java Virtual Machine throws an <code>Out</code><code>OfMemoryError</code>.
</ul><a name="22463"></a>
Sun's JDK 1.0.2 implementation of the Java Virtual Machine allocates fixed-size native method stacks of a single size. The size of its native method stacks may be set on virtual machine start-up using the "<code>-ss</code>" flag. The native method stack size limit can be used to limit memory consumption or to catch runaway recursions in <code>native</code> methods.<p>
<a name="23271"></a>
Sun's implementation does <i>not</i> currently check for native method stack overflow.<p>
<a name="17257"></a>
<hr><h2>3.6 Frames</h2>
<a name="1962"></a>
A Java Virtual Machine <i>frame</i> is used to store data and partial results, as well as to
perform dynamic linking, to return values for methods, and to dispatch exceptions.
<p><a name="15581"></a>
A new frame is created each time a Java method is invoked. A frame is destroyed when its method completes, whether that completion is normal or abnormal (by throwing an exception). Frames are allocated from the Java stack <a href="Overview.doc.html#6654">(§3.5.2)</a> of the thread creating the frame. Each frame has its own set of local variables <a href="Overview.doc.html#15722">(§3.6.1)</a> and its own operand stack <a href="Overview.doc.html#15725">(§3.6.2)</a>. The memory space for these structures can be allocated simultaneously, since the sizes of the local variable area and operand stack are known at compile time and the size of the frame data structure depends only upon the implementation of the Java Virtual Machine. <p>
<a name="15582"></a>
Only one frame, the frame for the executing method, is active at any point in a given thread of control. This frame is referred to as the <i>current frame</i>, and its method is known as the <i>current method</i>. The class in which the current method is defined is the <i>current class</i>. Operations on local variables and the operand stack always are with reference to the current frame. <p>
<a name="23270"></a>
A frame ceases to be current if its method invokes another method or if its method completes. When a method is invoked, a new frame is created and becomes current when control transfers to the new method. On method return, the current frame passes back the result of its method invocation, if any, to the previous frame. The current frame is then discarded as the previous frame becomes the current one. Java Virtual Machine frames may be naturally thought of as being allocated on a stack, with one stack per Java thread <a href="Concepts.doc.html#24465">(§2.17)</a>, but they may also be heap allocated. <p>
<a name="21717"></a>
Note that a frame created by a thread is local to that thread and cannot be directly referenced by any other thread.<p>
<a name="15722"></a>
<h3>3.6.1 Local Variables</h3>
<a name="15723"></a>
On each Java method invocation, the Java Virtual Machine allocates a Java frame
<a href="Overview.doc.html#17257">(§3.6)</a>, which contains an array of words known as its <i>local variables</i>. Local variables are addressed as word offsets from the base of that array.
<p><a name="15724"></a>
Local variables are always one word wide. Two local variables are reserved for each <code>long</code> or <code>double</code> value. These two local variables are addressed by the index of the first of the variables. <p>
<a name="23279"></a>
For example, a local variable with index <em>n</em> and containing a value of type <code>double</code> actually occupies the two words at local variable indices <em>n</em> and <em>n</em>+1. The Java Virtual Machine does not require <i>n</i> to be even. (In intuitive implementation terms, 64-bit values need not be 64-bit aligned in the local variables array.) Implementors are free to decide the appropriate way to divide a 64-bit data value between two local variables.<p>
<a name="15725"></a>
<h3>3.6.2 Operand Stacks</h3>
<a name="15726"></a>
On each Java method invocation, the Java Virtual Machine allocates a Java frame
<a href="Overview.doc.html#17257">(§3.6)</a>, which contains an <i>operand stack</i>. Most Java Virtual Machine instructions
take values from the operand stack of the current frame, operate on them, and return
results to that same operand stack. The operand stack is also used to pass arguments
to methods and receive method results.
<p><a name="15727"></a>
For example, the <i>iadd</i> instruction adds two <code>int</code> values together. It requires that the <code>int</code> values to be added be the top two words of the operand stack, pushed there by previous instructions. Both of the <code>int</code> values are popped from the operand stack. They are added, and their sum is pushed back onto the stack. Subcomputations may be nested on the operand stack, resulting in values that can be used by the encompassing computation. <p>
<a name="15728"></a>
Each entry on the operand stack is one word wide. Values of types <code>long</code> and <code>double</code> are pushed onto the operand stack as two words. The Java Virtual Machine does not require 64-bit values on the operand stack to be 64-bit aligned. Implementors are free to decide the appropriate way to divide a 64-bit data value between two operand stack words.<p>
<a name="15729"></a>
Values from the operand stack must be operated upon in ways appropriate to their types. It is incorrect, for example, to push two <code>int</code> values and then treat them as a <code>long</code>, or to push two <code>float</code> values then add them with an <i>iadd</i> instruction. A small number of Java Virtual Machine instructions (the <i>dup</i> instructions and <i>swap</i>) operate on run-time data areas as raw values of a given width without regard to type; these instructions must not be used to break up or rearrange the words of 64-bit data. These restrictions on operand stack manipulation are enforced, in the Sun implementation, by the <code>class</code> file verifier <a href="ClassFile.doc.html#8051">(§4.9)</a>.<p>
<a name="1963"></a>
<h3>3.6.3 Dynamic Linking</h3>
<a name="1913"></a>
A Java Virtual Machine frame contains a reference to the constant pool for the
type of the current method to support <i>dynamic linking</i> of the method code. The
<code>class</code> file code for a method refers to methods to be invoked and variables to be
accessed via symbolic references. Dynamic linking translates these symbolic
method references into concrete method references, loading classes as necessary
to resolve as-yet-undefined symbols, and translates variable accesses into appropriate offsets in storage structures associated with the runtime location of these
variables.
<p><a name="1972"></a>
This late binding of the methods and variables makes changes in other classes that a method uses less likely to break this code.<p>
<a name="1973"></a>
<h3>3.6.4 Normal Method Completion</h3>
<a name="1920"></a>
A method invocation <i>completes normally</i> if that invocation does not cause an exception (<a href="Concepts.doc.html#22727">§2.15</a>, <a href="Overview.doc.html#15494">§3.9)</a> to be thrown, either directly from the Java Virtual Machine or as a
result of executing an explicit <code>throw</code> statement. If the invocation of the current
method completes normally, then a value may be returned to the invoking method.
This occurs when the invoked method executes one of the return instructions
<a href="Overview.doc.html#9533">(§3.11.8)</a>, the choice of which must be appropriate for the type of the value being
returned (if any).
<p><a name="1980"></a>
The Java Virtual Machine frame is used in this case to restore the state of the invoker, including its local variables and operand stack, with the program counter of the invoker appropriately incremented to skip past the method invocation instruction. Execution then continues normally in the invoking method's frame with the returned value (if any) pushed onto the operand stack of that frame.<p>
<a name="22091"></a>
<h3>3.6.5 Abnormal Method Completion</h3>
<a name="22092"></a>
A method invocation <i>completes abnormally</i> if execution of a Java Virtual Machine
instruction within the method causes the Java Virtual Machine to throw an exception
(<a href="Concepts.doc.html#22727">§2.15</a>, <a href="Overview.doc.html#15494">§3.9)</a>, and that exception is not handled within the method. Evaluation of an
explicit <code>throw</code> statement also causes an exception to be thrown and, if the exception
is not caught by the current method, results in abnormal method completion. A
method invocation that completes abnormally never returns a value to its invoker.
<p><a name="22093"></a>
<h3>3.6.6 Additional Information</h3>
<a name="22094"></a>
A Java Virtual Machine frame may be extended with additional implementation-
specific information, such as debugging information.
<p><a name="16066"></a>
<hr><h2>3.7 Representation of Objects</h2>
<a name="16067"></a>
The Java Virtual Machine does not require any particular internal structure for
objects. In Sun's current implementation of the Java Virtual Machine, a reference to
a class instance is a pointer to a <em>handle</em> that is itself a pair of pointers: one to a table
containing the methods of the object and a pointer to the <code>Class</code> object that represents the type of the object, and the other to the memory allocated from the Java
heap for the object data.
<p><a name="21290"></a>
Other Java Virtual Machine implementations may use techniques such as inline caching rather than method table dispatch, and they may or may not use handles.<p>
<a name="12174"></a>
<hr><h2>3.8 Special Initialization Methods</h2>
<a name="16270"></a>
At the level of the Java Virtual Machine, every constructor <a href="Concepts.doc.html#16411">(§2.12)</a> appears as an
<i>instance initialization method</i> that has the special name <code><init></code>. This name is
supplied by a Java compiler. Because the name <code><init></code> is not a valid identifier, it
cannot be used directly by a Java programmer. Instance initialization methods
may only be invoked within the Java Virtual Machine by the <i>invokespecial</i> instruction, and they may only be invoked on uninitialized class instances. An instance
initialization method takes on the access permissions <a href="Concepts.doc.html#18914">(§2.7.8)</a> of the constructor
from which it was derived.
<p><a name="16262"></a>
At the level of the Java Virtual Machine, a class or interface is initialized <a href="Concepts.doc.html#19075">(§2.16.4)</a> by invoking its <i>class or interface initialization method</i> with no arguments. The initialization method of a class or interface has the special name <code><clinit></code>. This name is supplied by a Java compiler. Because the name <code><clinit></code> is not a valid identifier, it cannot be used directly by a Java programmer. Class and interface initialization methods are invoked implicitly by the Java Virtual Machine; they are never invoked directly from Java code or directly from any Java Virtual Machine instruction, but are only invoked indirectly as part of the class initialization process.<p>
<a name="15494"></a>
<hr><h2>3.9 Exceptions</h2>
<a name="22374"></a>
In general, throwing an exception results in an immediate dynamic transfer of control
that may exit multiple Java statements and multiple constructor invocations, static
and field initializer evaluations, and method invocations until a <code>catch</code> clause
<a href="Concepts.doc.html#22746">(§2.15.2)</a> is found that catches the thrown value.
<p><a name="23327"></a>
If no such <code>catch</code> clause is found in the current method, then the current method invocation completes abnormally <a href="Overview.doc.html#22091">(§3.6.5)</a>. Its operand stack and local variables are discarded and its frame is popped, reinstating the frame of the invoking method. The exception is then rethrown in the context of the invoker's frame, and so on continuing up the method invocation chain. If no suitable <code>catch</code> clause is found before the top of the method invocation chain is reached, the execution of the thread that threw the exception is terminated.<p>
<a name="22357"></a>
At the level of the Java Virtual Machine, each <code>catch</code> clause describes the Java Virtual Machine instruction range for which it is active, describes the types of exceptions that it is to handle, and gives the address of the code to handle it. An exception matches a <code>catch</code> clause if the instruction that caused the exception is in the appropriate instruction range, and the exception type is the same type as or a subclass of the class of exception that the <code>catch</code> clause handles. If a matching <code>catch</code> clause is found, the system branches to the specified handler. If no handler is found, the process is repeated until all the nested <code>catch</code> clauses of the current method have been exhausted.<p>
<a name="15775"></a>
The order of the <code>catch</code> clauses in the list is important. The Java Virtual Machine execution continues at the first matching <code>catch</code> clause. Because Java code is structured, it is always possible to arrange all the exception handlers for one method in a single list. For any possible program counter value, this list can be searched to find the proper exception handler, that is, the innermost exception handler that both contains the program counter value and can handle the exception being thrown.<p>
<a name="15776"></a>
If there is no matching <code>catch</code> clause, the current method is said to have an uncaught exception. The execution state of the invoker, the method that invoked this method, is restored. The propagation of the exception continues as though the exception had occurred in the invoker at the instruction that invoked the method actually raising the exception.<p>
<a name="15770"></a>
Java supports more sophisticated forms of exception handling through its <code>try-finally</code> and <code>try-catch-finally</code> statements. In such forms, the <code>finally</code> statement is executed even if no matching <code>catch</code> clause is found. The way the Java Virtual Machine supports implementation of these forms is discussed in Chapter  <a href="Compiling.doc.html#2839">7</a>, <a href="Compiling.doc.html#2989"></a><a href="Compiling.doc.html#2989">"Compiling for the Java Virtual Machine."</a><p>
<a name="15767"></a>
<hr><h2>3.10 The <code>class</code> File Format</h2>
<a name="15495"></a>
Compiled code to be executed by the Java Virtual Machine is stored in a binary file
which has a platform-independent format, the <code>class</code> file format. Given the aims of
the Java Virtual Machine, the definition of this file format is of importance equal to
its other components. The <code>class</code> file format precisely defines the contents of such a
file, including details such as byte ordering that might be taken for granted in a platform-specific object file format.
<p><a name="23328"></a>
Chapter <a href="ClassFile.doc.html#3660">4</a>, <a href="ClassFile.doc.html#4639">"The class File Format,"</a> covers the <code>class</code> file format in detail.<p>
<a name="7143"></a>
<hr><h2>3.11 Instruction Set Summary</h2>
<a name="2111"></a>
A Java Virtual Machine instruction consists of a one-byte <em>opcode</em> specifying the
operation to be performed, followed by zero or more <em>operands </em>supplying arguments
or data that are used by the operation. Many instructions have no operands and consist only of an opcode.
<p><a name="2073"></a>
Ignoring exceptions, the inner loop of the Java Virtual Machine execution is effectively<p>
<pre><br><a name="14812"></a> <code>do {
</code></pre><pre> <code> fetch an opcode;
</code> <code> if (operands) fetch operands;
</code> <code> execute the action for the opcode;
</code><a name="7542"></a> <code>} while (there is more to do);
</code><br></pre><a name="16703"></a>
The number and size of the additional operands are determined by the opcode. If an additional operand is more than one byte in size, then it is stored in big-endian order-high-order byte first. For example, an unsigned 16-bit index into the local variables is stored as two unsigned bytes <i>byte1</i> and <i>byte2</i> such that its value is <p>
<pre> <code>(</code><i>byte1</i> << <code>8) | </code><i>byte2
</i></pre><a name="21440"></a>
The bytecode instruction stream is only single-byte aligned. The two exceptions are
the <i>tableswitch</i> and <i>lookupswitch</i> instructions, which are padded to force internal
alignment of some of their operands on 4-byte boundaries.
<p><a name="2969"></a>
The decision to limit the Java Virtual Machine opcode to a byte and to forego data alignment within compiled code reflects a conscious bias in favor of compactness, possibly at the cost of some performance in naive implementations. A one-byte opcode precludes certain implementation techniques that could improve the performance of a Java Virtual Machine emulator, and it limits the size of the instruction set. Not assuming data alignment means that immediate data larger than a byte must be constructed from bytes at run time on many machines.<p>
<a name="7565"></a>
<h3>3.11.1 Types and the Java Virtual Machine</h3>
<a name="7566"></a>
Most of the instructions in the Java Virtual Machine instruction set encode type
information about the operations they perform. For instance, the <i>iload</i> instruction
loads the contents of a local variable, which must be an <code>int</code>, onto the operand stack.
The <i>fload</i> instruction does the same with a <code>float</code> value. The two instructions may
have identical implementations, but have distinct opcodes.
<p><a name="7572"></a>
For the majority of typed instructions, the instruction type is represented explicitly in the opcode mnemonic by a letter: <i>i</i> for an <code>int</code> operation, <i>l</i> for <code>long</code>, <i>s</i> for <code>short</code>, <i>b</i> for <code>byte</code>, <i>c</i> for <code>char</code>, <i>f</i> for <code>float</code>, <i>d</i> for <code>double</code>, and <i>a</i> for <code>reference</code>. Some instructions for which the type is unambiguous do not have a type letter in their mnemonic. For instance, <i>arraylength</i> always operates on an object that is an array. Some instructions, such as <i>goto</i>, an unconditional control transfer, do not operate on typed operands.<p>
<a name="16866"></a>
Given the Java Virtual Machine's one-byte opcode size, encoding types into opcodes places pressure on the design of its instruction set. If each typed instruction supported all of the Java Virtual Machine's runtime data types, there would be more instructions than could be represented in a byte. Instead, the instruction set of the Java Virtual Machine provides a reduced level of type support for certain operations. In other words, the instruction set is intentionally not orthogonal. Separate instructions can be used to convert between unsupported and supported data types as necessary.<p>
<a name="20055"></a>
<a href="Overview.doc.html#23711">Table 3.1</a> summarizes the type support in the instruction set of the Java Virtual Machine. Only instructions that exist for multiple types are listed. A specific instruction, with type information, is built by replacing the <i>T</i> in the instruction template in the opcode column by the letter in the type column. If the type column for some instruction template and type is blank, then no instruction exists supporting that type of operation. For instance, there is a load instruction for type <code>int</code>, <i>iload</i>, but there is no load instruction for type <code>byte</code>. <p>
<a name="23711"></a>
Note that most instructions in Table 3.1 do not have forms for the integral types <code>byte</code>, <code>char</code>, and <code>short</code>. When writing to its local variables or operand stacks, the Java Virtual Machine internally sign-extends values of types <code>byte</code> and <code>short</code> to type <code>int</code>, and zero-extends values of type <code>char</code> to type <code>int</code>. Thus, most operations on values of types <code>byte</code>, <code>char</code>, and <code>short</code> are correctly performed by instructions operating on values of type <code>int</code>. The Java Virtual Machine also treats values of Java type <code>boolean</code> specially, as noted in <a href="Overview.doc.html#22909">§3.2.4</a>.<p><Table Border="0">
<tr><th><b><i>opcode
</i></b>
<th><b><i><code>byte
</code></i></b>
<th><b><i><code>short
</code></i></b>
<th><b><i><code>int
</code></i></b>
<th><b><i><code>long
</code></i></b>
<th><b><i><code>float
</code></i></b>
<th><b><i><code>double
</code></i></b>
<th><b><i><code>char
</code></i></b>
<th><b><i><code>reference
</code></i></b>
<tr><td><a name="23757"></a>
<i>Tipush</i>
<td><a name="23759"></a>
<i>bipush</i>
<td><a name="23761"></a>
<i>sipush</i>
<td><a name="23763"></a>
<td><a name="23765"></a>
<td><a name="23767"></a>
<td><a name="23769"></a>
<td><a name="23771"></a>
<td><a name="23773"></a>
<tr><td><a name="23775"></a>
<i>Tconst</i>
<td><a name="23777"></a>
<td><a name="23779"></a>
<td><a name="23781"></a>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -