⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compiling.doc.html

📁 A Java virtual machine instruction consists of an opcode specifying the operation to be performed, f
💻 HTML
📖 第 1 页 / 共 5 页
字号:
</code><code>    return i + j;</code><code>}</code></pre></blockquote>compiles to<p><blockquote><pre>Method <code>int</code> <code>addTwoStatic(int,int)</code>   0 	iload_0   1	iload_1   2 	iadd   3 	ireturn</pre></blockquote>The only difference is that the method arguments appear starting in local variable 0 rather than 1.<p><a name="14787"></a><hr><h2>7.7    Invoking Methods</h2>The normal method invocation for a instance method dispatches on the runtime type of the object. (They are virtual, in C++ terms.) Such an invocation is implemented using the invokevirtual instruction, which takes as its argument an index to a runtimeconstant pool entry giving the fully qualified name of the class type of the object, the name of the method to invoke, and that method's descriptor <a href="ClassFile.doc.html#7035">(&#167;4.3.3)</a>. To invoke the <code>addTwo</code> method, defined earlier as an instance method, we might write<p><blockquote><pre><code>int add12and13() {</code><code>    return addTwo(12, 13);</code><code>}</code></pre></blockquote>This compiles to<p><blockquote><pre>Method <code>int</code> <code>add12and13()</code>   0 	aload_0			 	// Push local variable 0 (<code>this</code>)   1 	bipush 12			// Push <code>int</code> constant <code>12</code>   3 	bipush 13			// Push <code>int</code> constant <code>13</code>   5 	invokevirtual #4		// Method <code>Example.addtwo(II)I</code>   8	ireturn			 	// Return <code>int</code> on top of operand stack; it is				 	// the <code>int</code> result of <code>addTwo()</code></pre></blockquote><a name="4399"></a>The invocation is set up by first pushing a <code>reference</code> to the current instance, <code>this</code>, onto the operand stack. The method invocation's arguments, <code>int</code> values <code>12</code> and <code>13</code>, are then pushed. When the frame for the <code>addTwo</code> method is created, the arguments passed to the method become the initial values of the new frame's local variables. That is, the <code>reference</code> for <code>this</code> and the two arguments, pushed onto the operand stack by the invoker, will become the initial values of local variables 0, 1, and 2 of the invoked method. <p><a name="5962"></a>Finally, <code>addTwo</code> is invoked. When it returns, its <code>int</code> return value is pushed onto the operand stack of the frame of the invoker, the <code>add12and13</code> method. The return value is thus put in place to be immediately returned to the invoker of <code>add12and13</code>. <p><a name="10439"></a>The return from <code>add12and13</code> is handled by the ireturn instruction of <code>add12and13</code>. The ireturn instruction takes the <code>int</code> value returned by <code>addTwo</code>, on the operand stack of the current frame, and pushes it onto the operand stack of the frame of the invoker. It then returns control to the invoker, making the invoker's frame current. The Java virtual machine provides distinct return instructions for many of its numeric and <code>reference</code> data types, as well as a return instruction for methods with no return value. The same set of return instructions is used for all varieties of method invocations.<p><a name="10497"></a>The operand of the invokevirtual instruction (in the example, the runtime constant pool index #4) is not the offset of the method in the class instance. The compiler does not know the internal layout of a class instance. Instead, it generates symbolic references to the methods of an instance, which are stored in the runtime constant pool. Those runtime constant pool items are resolved at run time to determine the actual method location. The same is true for all other Java virtual machine instructions that access class instances.<p><a name="6012"></a>Invoking <code>addTwoStatic</code>, a class (<code>static</code>) variant of <code>addTwo</code>, is similar, as shown:<p><blockquote><pre><code>int add12and13() {</code><code>    return addTwoStatic(12, 13);</code><code>}</code></pre></blockquote>although a different Java virtual machine method invocation instruction is used:<p><blockquote><pre>Method <code>int add12and13()</code>   0 	bipush 12   2 	bipush 13   4 	invokestatic #3 		// Method <code>Example.addTwoStatic(II)I</code>   7 	ireturn</pre></blockquote>Compiling an invocation of a class (<code>static</code>) method is very much like compiling an invocation of an instance method, except <code>this</code> is not passed by the invoker. The method arguments will thus be received beginning with local variable 0 (see <a href="Compiling.doc.html#8556">Section 7.6, "Receiving Arguments"</a>). The invokestatic instruction is always used to invoke class methods.<p><a name="9398"></a>The invokespecial instruction must be used to invoke instance initialization methods (see <a href="Compiling.doc.html#4089">Section 7.8, "Working with Class Instances"</a>). It is also used when invoking methods in the superclass (<code>super</code>) and when invoking <code>private</code> methods. For instance, given classes <code>Near</code> and <code>Far</code> declared as<p><blockquote><pre><code>class Near {</code><code>    int it;</code><code>    public int getItNear() {</code><code>        return getIt();</code><code>    }</code><code>    private int getIt() {</code><code>        return it;</code><code>    }</code>}<code>class Far extends Near {</code><code>    int getItFar() {</code><code>        return super.getItNear();</code><code>    }</code><code>}</code></pre></blockquote>the method <code>Near.getItNear</code> (which invokes a <code>private</code> method) becomes<p><blockquote><pre>Method <code>int</code> <code>getItNear()</code>   0 	aload_0   1 	invokespecial #5 		// Method <code>Near.getIt()I</code>   4 	ireturn</pre></blockquote>The method <code>Far.getItFar</code> (which invokes a superclass method) becomes<p><blockquote><pre>Method <code>int</code> <code>getItFar()</code>   0 	aload_0   1 	invokespecial #4		// Method <code>Near.getItNear()I</code>   4	ireturn</pre></blockquote>Note that methods called using the invokespecial instruction always pass <code>this</code> to the invoked method as its first argument. As usual, it is received in local variable 0.<p><a name="4089"></a><hr><h2>7.8    Working with Class Instances</h2>Java virtual machine class instances are created using the Java virtual machine's new instruction. Recall that at the level of the Java virtual machine, a constructor appears as a method with the compiler-supplied name <code>&lt;init&gt;</code>. This specially named method is known as the instance initialization method <a href="Overview.doc.html#12174">(&#167;3.9)</a>. Multiple instance initialization methods, corresponding to multiple constructors, may exist for a given class. Once the class instance has been created and its instance variables, including those of the class and all of its superclasses, have been initialized to their default values, an instance initialization method of the new class instance is invoked. For example:<p><blockquote><pre><code>Object create() {</code><code>    return new Object();</code><code>}</code></pre></blockquote>compiles to<p><blockquote><pre>Method <code>java.lang.Object</code> <code>create()</code>   0 	new #1 				// Class <code>java.lang.Object</code>   3 	dup   4 	invokespecial #4 		// Method <code>java.lang.Object.&lt;init&gt;()V</code>   7 	areturn</pre></blockquote><a name="14907"></a>Class instances are passed and returned (as <code>reference</code> types) very much like numeric values, although type <code>reference</code> has its own complement of instructions, for example:<p><blockquote><pre><code>int i;					// An instance variable</code><code>MyObj example() {</code><code>    MyObj o = new MyObj();</code><code>    return silly(o);</code><code>}</code><code>MyObj silly(MyObj o) {</code><code>    if (o != null) {</code><code>        return o;</code><code>    } else {</code><code>        return o;</code><code>    }</code><code>}</code></pre></blockquote>becomes<p><blockquote><pre>Method <code>MyObj</code> <code>example()</code>   0 	new #2 				// Class <code>MyObj</code>   3 	dup   4 	invokespecial #5 		// Method <code>MyObj.&lt;init&gt;()V</code>   7 	astore_1   8 	aload_0   9 	aload_1  10 	invokevirtual #4 						// Method <code>Example.silly(LMyObj;)LMyObj;</code>  13 	areturnMethod <code>MyObj</code> <code>silly(MyObj)</code>   0 	aload_1   1 	ifnull 6   4	aload_1   5 	areturn   6 	aload_1   7 	areturn</pre></blockquote><a name="4716"></a>The fields of a class instance (instance variables) are accessed using the getfield and putfield instructions. If <code>i</code> is an instance variable of type <code>int</code>, the methods <code>setIt</code> and <code>getIt,</code> defined as<p><blockquote><pre><code>void setIt(int value) {</code><code>    i = value;</code><code>}</code><code>int getIt() {</code><code>    return i;</code><code>}</code></pre></blockquote>become<p><blockquote><pre>Method <code>void</code> <code>setIt(int)</code>   0 	aload_0   1 	iload_1   2 	putfield #4 			// Field <code>Example.i I</code>   5	returnMethod <code>int</code> <code>getIt()</code>   0 	aload_0   1 	getfield #4 			// Field <code>Example.i I</code>   4	ireturn</pre></blockquote>As with the operands of method invocation instructions, the operands of the putfield and getfield instructions (the runtime constant pool index #4) are not the offsets of the fields in the class instance. The compiler generates symbolic references to the fields of an instance, which are stored in the runtime constant pool. Those runtime constant pool items are resolved at run time to determine the location of the field within the referenced object.<p><a name="4091"></a><hr><h2>7.9    Arrays</h2>Java virtual machine arrays are also objects. Arrays are created and manipulated using a distinct set of instructions. The newarray instruction is used to create an array of a numeric type. The &#32;code<p><blockquote><pre><code>void createBuffer() {</code><code>    int buffer[];</code><code>    int bufsz = 100;</code><code>    int value = 12;</code><code>    buffer = new int[bufsz];</code><code>    buffer[10] = value;</code><code>    value = buffer[11];</code><code>}</code></pre></blockquote>might be compiled to<p><blockquote><pre>Method <code>void</code> <code>createBuffer()</code>   0 	bipush 100		// Push <code>int</code> constant 100 (<code>bufsz</code>)   2 	istore_2		// Store <code>bufsz</code> in local variable 2   3 	bipush 12		// Push <code>int</code> constant 12 (<code>value</code>)   5 	istore_3		// Store <code>value</code> in local variable 3   6	iload_2			// Push <code>bufsz</code>...   7	newarray <code>int</code>		// ...and create new array of <code>int</code> of that length   9 	astore_1		// Store new array in <code>buffer</code>  10 	aload_1			// Push <code>buffer</code>  11 	bipush 10		// Push <code>int</code> constant <code>10</code>  13 	iload_3			// Push <code>value</code>  14 	iastore			// Store value at <code>buffer[10]</code>  15 	aload_1			// Push <code>buffer</code>  16 	bipush 11		// Push <code>int</code> constant <code>11</code>  18 	iaload			// Push value at <code>buffer[11]</code>... &#32; 19 	istore_3		// ...and store it in <code>value</code>  20	return</pre></blockquote><a name="6189"></a>The anewarray instruction is used to create a one-dimensional array of object references, for example:<p><blockquote><pre><code>void createThreadArray() {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -