JVM和内存

  JVM和内存

1.   一般垃圾回收器包含哪些空间?

所有的回收器类型都是基于分代技术。Java HotSpot虚拟机包含三代,年轻代(Young Generation)、年老代(Old Generation)、永久代(Permanent Generation)。

永久代

存储类、方法以及它们的描述信息。可以通过-XX:PermSize=64m和-XX:MaxPermSize=128m两个可选项指定初始大小和最大值。通常 我们不需要调节该参数,默认的永久代大小足够了,不过如果加载的类非常多,不够用了,调节最大值即可。

年老代

主要存储年轻代中经过多个回收周期仍然存活从而升级的对象,当然对于一些大的内存分配,可能也直接分配到永久代(一个极端的例子是年轻代根本就存不下)。

年轻代

绝大多数的内存分配回收动作都发生在年轻代。如下图所示, 年轻代被划分为三个区域,原始区(Eden)和两个小的存活区(Survivor),两个存活区按功能分为From和To。绝大多数的对象都在原始区分配,超过一个垃圾回收操作仍然存活的对象放到存活区。

2.   一般垃圾回收器中堆空间和永久代空间的区别是什么?

(1)    堆用来保存实例和数组,所有的线程共享这一区域

(2)    永久代空间用来保存类、方法以及它们的描述信息

JVM内存结构:方法区+堆+栈+本地方法栈

垃圾回收空间划分:年轻代+年老代+永久代

年轻代+年老代=堆

永久代=方法区

3.   垃圾回收器中的永久代空间能被回收吗?

永久代的垃圾回收和老年代的垃圾回收是绑定的,一旦其中一个区域被占满,这两个区都要进行垃圾回收。但是有一个明显的问题,由于我们可以通过‑XX:MaxPermSize 设置永久代的大小,一旦类的元数据超过了设定的大小,程序就会耗尽内存,并出现内存溢出错误(OOM)。

备注:在JDK7之前的HotSpot虚拟机中,纳入字符串常量池的字符串被存储在永久代中,因此导致了一系列的性能问题和内存溢出错误。

着Java8的到来,我们再也见不到永久代了。但是这并不意味着类的元数据信息也消失了。这些数据被移到了一个与堆不相连的本地内存区域,这个区域就是我们要提到的元空间。

4.   永久代是怎么样才会出现内存溢出?

永久代主要存放类、方法及其描述信息,但这些成员的大小超过设定的MaxPermSize时,就会出现内存溢出。

也可能通过CGLIB动态生成类,这样也可能会出现内存溢出。

5.   一个对象在什么情况下才会被垃圾回收器回收?

垃圾回收器每隔一段时间或者达到一定的阀值,就会执行回收操作,如果对象没被引用时,就会被垃圾回收器回收。

确定对象是垃圾

(1)    引用计数器算法,JDK1.1后这个算法淘汰

(2)    根搜索算法

根搜索方法是通过一些GC Roots”对象作为起点,从这些节点开始往下搜索,搜索通过的路径成为引用链(Reference Chain),当一个对象没有被GC Roots的引用链连接的时候,说明这个对象是不可用的。

GC Roots对象包括:

a) 虚拟机栈(栈帧中的本地变量表)中的引用的对象。

b) 方法区域中的类静态属性引用的对象。

c) 方法区域中常量引用的对象。

d) 本地方法栈中JNINative方法)的引用的对象。

垃圾回收算法

(1)    标记-清除算法

(2)    复制算法

(3)    标记整理算法

(4)    分代收集

新生代---标记清除算法

老年代—整理算法

6.   什么是弱引用?

http://zhangjunhd.blog.51cto.com/113473/53092/

⑴强引用(StrongReference

强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。

 

⑵软引用(SoftReference

如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存(下文给出示例)。

软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。

 

⑶弱引用(WeakReference

弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。

弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

 

⑷虚引用(PhantomReference

“虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。

虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。

ReferenceQueue queue = new ReferenceQueue ();

PhantomReference pr = new PhantomReference (objectqueue);

程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

猜你喜欢

转载自blog.csdn.net/qq_30764991/article/details/80574316