菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
294
0

JVM

原创
05/13 14:22
阅读数 38090

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这一及时编译方式,可以将字节码直接转化成高性能的本地机器码,这同样是虚拟机的一个构成部分。

发表评论

0/200
294 点赞
0 评论
收藏
为你推荐 换一批