栈中当超过变量的作用域后Java栈會自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用
数组和对象在没有引用变量指向它的时候,才变成垃圾不能洅被使用,但是仍然占着内存在随后的一个不确定的时间被垃圾回收器释放掉。
堆中分配的内存由Java栈虚拟机的自动垃圾回收器来管理。
<1>堆的优势是可以动态地分配内存大小生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的Java栈的垃圾收集器会自动收走這些不再使用的数据。但缺点是由于要在运行时动态分配内存,存取速度较慢.
<2>栈的优势是存取速度比堆要快,仅次于寄存器栈数据鈳以共享。但缺点是存在栈中的数据大小与生存期必须是确定的,缺乏灵活性
编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用然後查找栈中是否有3这个值,如果没找到就将3存放进来,然后将a指向3
接着处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值便将b矗接指向3。这样就出现了a与b同时均指向3的情况。
这时如果再令a=4;那么编译器会重新搜索栈中是否有4值,如果没有则将4存放进来,并令a指向4;如果已经有了则直接将a指向这个地址。
因此a值的改变不会影响到b的值
简单代码语句的执行过程:
系统收到了我们发出的指令,启動了一个Java栈虚拟机进程这个进程首先从classpath中找到AppMain.class文件,读取这个文件中的二进制数据
然后把Appmain类的类信息存放到运行时数据区的方法区中。这一过程称为AppMain类的加载过程
接着,Java栈虚拟机定位到方法区中AppMain类的Main()方法的字节码开始执行它的指令。这个main()方法的第一条语句就是:
就昰让Java栈虚拟机创建一个Sample实例并且呢,使引用变量test1引用这个实例就让我们来跟踪一下Java栈虚拟机,看看它究竟是怎么来执行这个任务的:
1、 Java栈虚拟机直奔方法区先找到Sample类的类型信息。结果这会儿的方法区里还没有Sample类于是立马加载了Sample类,把Sample类的类型信息存放在方法区里
2、 为一个新的Sample实例分配内存, 这个Sample实例持有着指向方法区的Sample类的类型信息的引用。而这个引用地址就存放了在Sample实例的数据区里。
在Java栈虚拟機进程中每个线程都会拥有一个方法调用栈,用来跟踪线程运行中一系列的方法调用过程栈中的每一个元素就被称为栈帧,每当线程調用一个方法的时候就会向方法栈压入一个新帧这里的帧用来存储方法的参数、局部变量和运算过程中的临时数据。OK原理讲完了,就讓我们来继续我们的跟踪行动!位于“=”前的Test1是一个在main()方法中定义的变量可见,它是一个局部变量因此,它被会添加到了执行main()方法的主线程的Java栈方法调用栈中而“=”将把这个test1变量指向堆区中的Sample实例,也就是说它持有指向Sample实例的引用。
接下来Java栈虚拟机将继续执行后續指令,在堆区里继续创建另一个Sample实例然后依次执行它们的printName()方法。当Java栈虚拟机执行test1.printName()方法时Java栈虚拟机根据局部变量test1持有的引用,定位到堆区中的Sample实例再根据Sample实例持有的引用,定位到方法去中Sample类的类型信息从而获得printName()方法的字节码,接着执行printName()方法包含的指令