java 基础拾遗

1、C/C++ goto 的实现,java中保留了goto关键字,但是已经没有继续使用,可以使用label(标签)和continue,break使用

label1: for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 10; ++j) {
				if (j > 2) {
					break label1;
				}
				System.out.print(i * 10 + j+",");
			}
		}
以上使用break输出0,1,2

label1: for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 10; ++j) {
				if (j > 2) {
					continue label1;
				}
				System.out.print(i * 10 + j+",");
			}
		}
以上使用continue输出0,1,2,10,11,12

2、JVM何时执行垃圾回收?

在JVM面临内存耗尽的情况下,JVM执行垃圾回收,以恢复内存。

3、finalize()用于检查在对象进行垃圾回收的应用场景:

用于检查在对象进行垃圾回收前应有的状态。

4、GC(垃圾回收器)如何工作?

①JVM在堆上分配内存的方式:更像一个传送带,每分配一个新对象,它就向前移动一格。

②GC一面回收空间,一面使对象紧密排列。这样堆指针可以更容易靠近传送带的开始处,也就尽量避免了页面错误。

GC依据思想:对于任何活的对象(不应该被垃圾回收),一定能最终追溯到其存活在堆栈或静态存储区之中的引用。这个引用链条可能会穿过数个对象层次。由此,如果在堆栈和静态存储区开始,遍历所有的引用,就能找到所有活的对象。对于发现的每个引用,必须追踪它所引用的对象,然后是此对象包含的所有引用,如此反复进行,指导“根源于堆栈和静态存储区的引用”所形成的网络全部被访问为止。你所访问 过的对象必须都是活的。注意,这就解决了“交互自引用的对象组”的问题--这种对象根本不会被发现,因此就被自动回收了。


在这中方式下,java虚拟机将采用一种自适应的垃圾回收技术。

有一种做法名为 停止-复制(stop and copy),先暂停程序的运行(所以他/她不属于后台回收模式),然后将所有存活的对象从当前堆复制到另一个堆,没有被复制的全部都是垃圾。当对象被复制到新堆时,它们是一个挨着一个的,所以新堆保持紧凑排列,然后就可以按前述方法简单、直接地分配空间了。当把对象从一处搬到另一处时,所有指向它的那些引用都必须修正。位于静态存储区的引用可以直接被修正,但可能还有其他指向这些对象的引用,它们在遍历的过程汇总才能被找到(可以想象成有个表格,将旧地址映射到新地址)。

缺点:效率会降低, 理由有①首先得有两个堆,从而维护比实际需要多一倍的空间;②程序进入稳定状态后,可能只会产生少量垃圾,甚至没有垃圾。尽管如此,复制式回收器仍然会将所有内存从一处复制到另一处,这很浪费。

为了避免如上缺点,一些java虚拟机会进行检查:要是没有新的垃圾产生,就会转换到另一种工作模式(即“自适应”)。这种模式称为标记 - 清扫(mark-and-sweep),Sun公司早期版本的JVM使用了这种技术。对于一般用途而言“标记-清扫”方式速度相当慢,但当你知道只会产生少量垃圾甚至不会产生垃圾时,它的数度就很快了。

标记-清扫(mark-and-sweep)所依据的思路同样是 从堆栈和静态存储区出发,遍历所有的引用,进而找出所有存活对象,每当它好到一个存活对象。,就会给对象设一个标记,这个过程中不会回收任何对象。只有全部标记工作完成的时候,清理动作才会开始。在清理过程总,没有标记的对象将被释放,不会发生任何复制动作,所以,剩下的堆空间是不连续的,GC要是希望得到连续空间的话就得重新整理剩下的对象。

以上问题:GC执行的时候,程序必须暂停。



猜你喜欢

转载自blog.csdn.net/cherishpart/article/details/50883682
今日推荐