JVM常见面试题1

1.JVM 内存划分。

①.方法区(线程共享):常量、静态变量、JIT(即时编译器) 编译后的代码,class的相关信息也都在方法区;
②.堆内存(线程共享)(堆):存储对象实例以及数组容器,垃圾回收的主要场所;
③.程序计数器: 当前线程执行的字节码的位置指示器;
④.虚拟机栈(栈):保存局部变量、基本数据类型变量以及堆内存中某个对象的引用变量;
⑤.本地方法栈 :为 JVM 提供使用 native 方法的服务。

2.Java中垃圾回收有什么目的?垃圾回收? java的内存管理 对象的分配与释放?

垃圾回收的目的是识别并且丢弃应用不再使用的对象来释放和重用资源。
垃圾回收主要从三个方面去理解:
①哪些对象需要回收?引用计数法,和可达性分析算法。
②何时进行回收?CPU空闲,堆满,system.gc()。
③如何回收?标记-清除算法,复制算法,标记-整理算法,分代收集算法。
java的内存管理 对象的分配与释放
分配
程序员通过new为每个对象申请内存空间(基本类型除外),所有对象都在堆中分配空间;释放:对象的释放是由垃圾回收机制决定和执行的。
Java内存分为两种:栈内存和堆内存
(1)在函数中定义的基本类型变量(即基本类型的局部变量)和对象的引用变量(即对象的变量名)都在栈内存中分配;
(2)堆内存用来存储由new创建的对象和数组以及对象的实例变量(即全局变量)
(3)堆的优势是可以动态分配内存大小,生存期也不必事先告诉编译器,因为它是运行时动态分配内存的;缺点是运行时动态分配内存,存取速度慢;
(4)栈的优点是存取速度较快仅仅次于CPU中的寄存器,且栈数据可以共享;但是栈中的数据大小和生存期是必须确定的,缺乏灵活性;
(5)只有一个堆区被所有线程共享,堆区不存放基本类型和对象引用只存放对象本身
(6)每个线程包含一个栈区,保存基础数据类型的对象和自定义对象的引用,每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问
还有一个方法区:存储所有对象数据共享区域,存储静态变量和普通方法、静态方法、常量、字符串常量等信息,又叫静态区,是所有线程共享的。
Java对象销毁
Java中垃圾收集器自动地定期扫描Java对象的动态内存,并将所有的引用对象加上标记,在对象运行结束后(无引用变量对该对象进行关联),清除其标记,并将所有无标记的对象作为垃圾进行回收,释放垃圾对象所占的内存空间。
对象运行结束后或生命周期结束时,将成为垃圾对象,但并不意味着就立即会被回收,仅当垃圾收集器空闲或内存不足时,才会回收他们。
Java中每个对象都拥有一个finalize()方法:
垃圾回收器在回收对象时自动调用对象的finalize()方法来释放系统资源。

3.哪些对象可以被作为GC Roots对象?(哪些对象会一直存活?)

①虚拟机栈(栈帧中的本地变量表)中引用的对象;
②本地方法中JNI(即一般说的native方法)引用的对象;
③方法区中静态变量和常量引用的对象。

4.垃圾回收的过程?垃圾回收分代收集算法?为什么会有两个Survivor区?new一个对象会保存在哪里?

当系统创建一个对象的时候,总是在Eden区操作,当这个区满了,那么就会触发一次YoungGC,也就是年轻代的垃圾回收。一般来说这时候不是所有的对象都没用了,所以就会把还能用的对象复制到From区。 这样整个Eden区就被清理干净了,可以继续创建新的对象,当Eden区再次被用完,就再触发一次YoungGC,然后呢,注意,这个时候跟刚才稍稍有点区别。这次触发YoungGC后,会将Eden区与From区还在被使用的对象复制到To区, 再下一次YoungGC的时候,则是将Eden区与To区中的还在被使用的对象复制到From区。 经过若干次YoungGC后,有些对象在From与To之间来回游荡,这时候From区与To区亮出了底线(阈值),这些家伙要是到现在还没挂掉,对不起,一起滚到(复制)老年代吧。 老年代经过这么几次折腾,也就扛不住了(空间被用完),好,那就来次集体大扫除(Full GC),也就是全量回收,一起滚蛋吧。
我是一个普通的Java对象,我出生在Eden区,在Eden区我还看到和我长的很像的小兄弟,我们在Eden区中玩了挺长时间。有一天Eden区中的人实在是太多了,我就*去了Survivor区的“From”区,自从去了Survivor区,我就开始漂了,有时候在Survivor的“From”区,有时候在Survivor的“To”区,居无定所。直到我18岁的时候,爸爸说我成人了,该去社会上闯闯了。于是我就去了年老代那边,年老代里,人很多,并且年龄都挺大的,我在这里也认识了很多人。在年老代里,我生活了20年(每次GC加一岁),然后被回收。
分代垃圾回收算法来回收垃圾,思想也很简单,就是根据对象的生命周期将内存划分,然后进行分区管理。在Java虚拟机分代垃圾回收机制中,应用程序可用的堆空间可以分为年轻代与老年代,然后呢,年亲代有被分为Eden区,From区与To区。
年轻代:Minor GC;老年代:Major GC(因为Major GC一般伴随着Minor GC,也可以看做触发了Full GC)。
先看看为什么要有Survivor区:如果没有Survivor,Eden区每进行一次Minor GC,存活的对象就会被送到老年代。老年代很快被填满,触发Major GC(Full GC),Full GC消耗的时间是非常可观的,所以我们需要减少老年代的GC→减少老年代被填满。
再看看为什么有两个Survivor区:刚刚新建的对象在Eden中,一旦Eden满了,触发一次Minor GC,Eden中的存活对象就会被移动到Survivor区。这样继续循环下去,下一次Eden满了的时候,问题来了,此时进行Minor GC,Eden和Survivor各有一些存活对象,如果此时把Eden区的存活对象硬放到Survivor区,很明显这两部分对象所占有的内存是不连续的,也就导致了内存碎片化。所以应该建立两块Survivor区(S0和S1),刚刚新建的对象在Eden中,经历一次Minor GC,Eden中的存活对象就会被移动到第一块S0,Eden被清空;等Eden区再满了,就再触发一次Minor GC,Eden和S0中的存活对象又会被复制送入第二块S1(这个过程非常重要,因为这种复制算法保证了永远有一个survivor space是空的,另一个非空的survivor space无碎片)。

JVM常见面试题1JVM常见面试题1 中国加油武汉加油 发布了11 篇原创文章 · 获赞 4 · 访问量 403 私信 关注
上一篇:「每日五分钟,玩转JVM」:对象从哪来


下一篇:(模板)hdoj5977 Garden of Eden(点分治)