1.JVM中有哪几块内存区域?Java 8之后对内存分代做了什么改进?
tomcat部署,tomcat自己就是基于java来开发的,我们启动的不是自己的系统,是一个tomcat是一个jvm进程,我们写得系统只不过是一些代码,放在tomcat的目录里,tomcat会加载我们的代码到jvm中去。
JVM最常用的内存区域有三块 栈内存,堆内存和永久代。栈内存是线程每个线程独享的,堆内存是共享的,永久代中存储的是类的信息。
java8 之后将永久代中的常量池放到了堆内存中,永久代变成了metaspace(元区域)。
2.你知道JVM是如何运行起来的吗?堆内存中对象的分配的基本策略?
堆空间的基本结构:
新生代:eden区、s0区、s1区 默认大小分配8:1:1
老年代:tentired区
Minor Gc(新生代垃圾回收)和Full/Major Gc(老年代垃圾回收)有什么不同?
大多数情况下,对象在新生代中eden区分配。当Eden区没有足够的空间进行分配时,虚拟机将发起一次Minor Gc。
- 新生代GC:指发生新生代的垃圾收集动作,Minor GC非常频繁,回收速度一般比较快
- 老年代Gc:指发生在老年代的GC,出现Major GC经常会伴随至少一次Minor GC(并非绝对),Major GC的速度一般会比MinorGC慢10倍以上。
3.说说JVM在哪些情况下会触发垃圾回收可以吗?
我们的jvm的内存其实是有限制的,不可能是无限的,昂贵的资源,2核4G的机器,堆内存也就2GB左右,4核8G的机器堆内存也就4G左右,栈内存也需要空间,metaspace区域放类信息也需要空间。
jvm中有一个内存分代模型,年轻代和老年代,加在一起是堆内存,其中年轻代又分为三部分。年轻代和老年代的比例是我们可以设置的。
比如说年轻代一共是2GB内存,给老年代是2GB内存,默认情况下eden和2个s的比例是:8:1:1,eden是1.6GB, s是0.2GB
如果eden区域满了,此时必然触发垃圾回收,young gc ,ygc。谁是可以回收的垃圾对象?没有被引用的对象就是可以被回收的对象。
4.说说JVM的年轻代垃圾回收算法?对象什么时候转移到老年代?
垃圾回收有一个概念,叫做stop the world,停止你的jvm里的工作线程的运行,然后扫描所有的对象,判断哪些可以回收,哪些不可以回收。
年轻代,大部分情况下,对象生存周期是很短的,可能0.01ms之内,线程执行了3个方法,创建了几个对象,0.01ms之后方法就都执行结束了,此时那几个对象就会在0.01ms之内变成垃圾,可以回收了。
复制算法,一次young gc,年轻代的垃圾回收。将eden中存活的对象复制到s1中,清空eden:
将s1和eden中存活的复制到s2中,清空eden和s1;将s2和eden存活的复制到s1中,清空eden和s2.
三种场景,第一种场景,有的对象在年轻代里面熬过了很多次的垃圾回收,例如15次垃圾回收,此时会认为这个对象是要长期存活的对象。例如Spring容器中的bean对象。
第二种情况就是s区放不下存活的对象。
第三种情况就是特别大的对象。反复移动大对象消耗性能。
5.说说老年代的垃圾回收算法?常用的垃圾回收器都有什么?
老年代对象越来越多,老年代内存空间也会满,是不是可以使用类似的年轻代的复制算法?
答案是否定的,因为在老年代的对象中,很多都是长期引用的,spring容器管理的各种bean。
长期存活的对象是比较多的,可能甚至都有几百mb
对老年代而言,他里面的垃圾对象可能是没有那么多的。一开始采用标记-清理的方式,找出那些垃圾对象,然后直接把垃圾对象在老年代里清理掉,这样就会产生内存 碎片的问题。
后来采用标记-整理的方法,把老年代里的存活对象标记出来,移动到一起,存活对象压缩到一片内存空间去
剩余的空间都是垃圾整个给清理掉,剩余的都是连续的可用的内存空间,解决了内存碎片的问题。
垃圾回收器
parnew (新生代)+ cms(老年代)的组合, g1 直接分代回收 。g1可以实现新生代和老年代的垃圾一起回收。新版本,慢慢的就是主推g1垃圾回收器了,以后会淘汰掉parnews+cms组合,但是现在使用jdk8~jdk9居多,所以还是parnew+cms组合居多。
cms分成好几个阶段,初始标记,并发标记,并发清理等等,老年代垃圾回收是比较慢的,一般起码比年轻代垃圾回收慢个10倍以上。所以将它拆分成几个阶段,尽可能得让其和运行的其它线程并发执行。
6.谈谈你对java跨平台性的理解?为什么java可以一次编译到处运行?
不是说java语言可以跨平台,而是各个不同的平台都可以有让java语言运行的环境而已。
程序从源码到运行可以分为以下几个阶段,编码-编译-运行-调试。java在编译阶段体现了跨平台的特性。编译的过程大概是这样的:首先将java源码转化成class字节码文件,这是第一次编译,class字节码文件就是可以到处运行的文件。然后java字节码会被转化为目标机器的机器代码,这是由JVM来执行的,就是java的第二次编译。
“到处运行”的关键和前提就是JVM。因为在第二次编译的过程中JVM起着至关重要的作用。在可以运行java虚拟机的地方都内含着一个JVM操作系统。从而实现到处运行的效果。需要强调的是,java不是编译机制,而是解释机制。java字节码的设计充分考虑了JIT这一及时编译方式,可以将字节码直接转化成高性能的本地机器码,这同样是虚拟机的一个构成部分。
© 著作权归作者所有
发表评论