Java 引用传递的实验

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/rongdongzhu1/article/details/49689005

jasmin  源代码

Compiled from "Main.java"
class Modify {
  Modify();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public void ModifyStr(MyString);
    Code:
       0: aload_1														// *把局部变量#1中的地址压栈(局部变量#1存储函数的第一个实参 #2...#254 依次类推)
       1: iconst_m1													// *把常数-1压入栈
       2: putfield      #2                  // *Field MyString.a:I (a=-1)
       5: return
}



Compiled from "Main.java"
class MyString {
  public int a;

  MyString();
    Code:
       0: aload_0
       1: invokespecial #1              // Method java/lang/Object."<init>":()V
       4: return
}



Compiled from "Main.java"
public class Main {
  public Main();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
    	// *在堆中实例化	MyString,并将地址存在局部#1中
       0: new           #2                  // class MyString  *在堆中创建新的对象 并把地址压栈
       3: dup				    // *复制栈顶一个字并压入栈中
       4: invokespecial #3                  // Method MyString."<init>":()V *调用构造函数
       7: astore_1			    // *从栈顶弹出一个地址 并存储在局部变量#1中
      // *在堆中实例化	Modify,并将地址存在局部#2中
       8: new           #4                  // class Modify
      11: dup
      12: invokespecial #5                  // Method Modify."<init>":()V
      15: astore_2
      
      16: aload_1			    // *把局部变量#1中的地址压入栈(MyString实例化对象的地址)
      17: bipush        10		    // *将常数10压入栈
      19: putfield      #6                  // Field MyString.a:I *从栈中弹出一个地址和值,并将值存到指定的对象域中(s.a = 10;)
      22: aload_2			    // *把局部变量#2中的地址压入栈(Modify实例化对象的地址)
      23: aload_1			    // *把局部变量#1中的地址压入栈(MyString实例化对象的地址)
      
      /*
			 * invokevirtual 调用对象的实例方法按栈中如下次序调用
			 * argN	
			 * ...
			 * arg2
			 * arg1
			 * address 对象的地址 
			 * 在此例中 aload_2 作为对象的地址首先入栈 aload_1作为参数而后入栈
			 */
			 
      24: invokevirtual #7                  // Method Modify.ModifyStr:(LMyString;)V
      27: return
}

/*  结论:
 * 		当 new 一个新的对象时,jvm会自动在堆区开辟空间用以存储对象,并且会把对象的地址自动压入栈
 *		在此例中用汇编指令astore_1 astore_2 分别把对象的地址存储在局部变量 #1 #2中,然后我们使用对象时,
 *		实际上是通过存储在局部变量中的对象的地址来找到堆中的对象.用invokevirtual调用方法时,传递的是
 *		对象的地址(详见上面分析)
 */



Java 源代码

public class Main {
	public static void main(String[] arge){
		MyString s = new MyString();
		Modify m = new Modify();
		s.a = 10;
		m.ModifyStr(s);
	}
}



class MyString{
	public int a;
	
}

class Modify{
	public void ModifyStr(MyString str){
		str.a = -1;
	}
}



猜你喜欢

转载自blog.csdn.net/rongdongzhu1/article/details/49689005