大家好!我是本公众号唯一官方指定没头屑的小便--怕屁林。

 

JVM,全称Java Virtual Machine,作为执行Java程序的容器,几乎代理了Java内存与服务器内存的交互,可以说是程序拥有自己专属的内存的一样,这样方便了Java程序在各个操作系统上运行,因为各个系统安装了JVM即可。有意思的是,现在使用JVM的不止Java,也有其他语言可以运行在这之上。

 

第一道常规问题几乎就是,说下JVM里面有什么?就是堆、方法区/元空间/直接内存,不同JDK版本这个不同,然后线程私有的就是程序计数器、虚拟机栈、本地方法栈。问过JVM里面哪个部位不会发生OOM,其实就是程序计数器不会发生,它的作用也是保存下条指令、分支,循环,跳转、异常处理,线程恢复的位置。创建对象占用的内存就是通过堆来分配的,包括对象和数组的创建,同时也是垃圾收集器的管理区域,而且JDK7之后也把字符串常量池放到了这里来。线程私有的虚拟机栈和本地方法栈则各自保存执行方法和native方法中局部变量,操作数栈,动态链接,方法出入口信息。

 

堆里面产生的对象越来越多肯定是不行的,到了一定程度的时候就需要进行垃圾回收。堆里面垃圾回收区域分为eden、from survivor、tosurvivor,或者说S0和S1、还有old老年区。这里是一个分代回收的方式,为对象分配内存会在eden区进行,当eden区大到装不下的时候,就会发生一次minor gc,将eden区域中还能活的对象内存复制到S0,下一次再gc的时候,会将eden和S0的存活对象复制到S1,再下次就是将eden和S1的存活对象复制到S0,周而复始,当复制次数超过默认的15次的时候,就会进行old老年区,此外大对象是直接进入老年区的。当老年区也达到一定大小的时候,会发生full gc。full gc要比minor gc慢很多,所以要尽量减少full gc,例如老年区设置大一点。也有建议是full gc之前进行一次minor gc,因为老年区对象中有很多引用来自年轻代,一次minor gc可以整理一下,从而高效执行full gc。

 

如何判断一个对象是可以回收的呢?第一个引用计数法,就是多了一个引用就加一,少了一个引用就减一,零的时候就是没有引用了,但是这样如果两个对象互相引用,那么就永远不能回收了。第二个可达性分析法,一些虚拟机栈中引用的对象、方法区类静态属性引用的对象-方法区常量池引用的对象、本地方法栈JNI引用的对象作为一个根节点,查出它们引用的对象,构造出它们的引用树,不在这些树上的对象就可以回收了。

 

知道哪些垃圾收集器吗?收集器是围绕复制、标记-清除、标记-整理这几个算法展开的。像新生代的垃圾收集器就有serial单线程回收、ParNew多线程回收,Parallel Scavenge注重吞吐量的并发垃圾回收。老年代垃圾回收有serial old、Parallel old、CMS并发标记清除,以获取最短回收停顿时间为目标的收集器,基本实现垃圾回收和用户线程同时工作,整堆收集器有G1,一个维护了回收优先级列表的收集器,面向服务器的。

 

有没有过JVM调优经历呢?肯定有的,一般而言,项目上线后,堆大小是不完全确定的,需要调整,使用参数-Xms初始化堆大小和-Xmx堆最大多少,很多配置是这两个参数保持一样,建议是物理内存的二分之一和三分之一,-Xmn则是设置年轻代的大小,像之前上线了一个项目因为忙着服务器前前后后的软件安装,没有考虑这些参数,后面查看GC的情况时,发现minor gc和full gc次数不少,再查看堆分区大小的设置,的确默认的都比较小,是导致频繁gc的根源,接着修改为物理内存的二分之一,就没有再发生gc了,这个情况或许还能把堆调小一点。-XX:NewRatio是设置新生代和老年代的比例,-XX:SurvivorRatio则是设置eden和surivior的比例。-XX:+HeapDumpOnOutOfMemoryError则可以保存发生OOM时的实际数据。对于设置什么样的收集器,则应该查看文档来设置。

 

怎么看查看应用的JVM信息?首先使用JPS命令,得到应用的PID,就可以用jinfo -flag PID查看参数设置情况,使用jmap -heap PID查看分代配置情况,使用jstat -gcutil PID则可以查看gc发生的统计信息。

 

在编程的时候,会见到每个对象都有finalize()方法,调用它意味着什么?可达性分析中,分析出对象可以回收,如果类有覆盖finalize方法,会放到一个F-Queue中,虚拟机触发一个线程去执行,但不会承诺一直等待它运行完避免死锁从而内存回收系统崩溃,GC对处于F-Queue中的对象进行第二次被标记,这时该对象将会被移除“即将回收”集合,等待回收。

 

其实JVM分配内存,涉及到了对象的创建过程,对象创建的过程包括类加载检查、分配内存、初始化零值、设置对象头、执行init方法。类加载检查就是检查这个类信息有没有加载到方法区或者元空间中,设置对象头则是一些hascode、gc分代年龄等。其中分配内存涉及到在堆上面寻找空闲空间,方式有"指针碰撞"和"空闲列表",指针碰撞是维护一个指针,指向空闲和非空闲区域,对象需要多少内存则可以通过滑动指针类分配。空闲列表则是维护一个记录空闲位置的列表,需要多大的内存在列表上一查就清楚了。采用哪种方式取决于内存是否规整。分配内存也涉及并发线程安全问题,解决办法是在eden区上划分很多的TLAB小区,分配内存在TLAB上分配各不打扰,如果TLAB分配不下或都要用完了,则走CAS解决冲突分配内存。

 

第一版Java面试知识点汇总下载(有不少错别字和没更新的):https://pan.baidu.com/s/1MxKXIZtoBd57pTwTIDyrgA 提取码: 3arb。

相关阅读:

飞越面试官(二)--JUC

飞越面试官(一)--Java基础

重磅!两万字Java面试知识点汇总发布!

个人公众号,关注可第一时间获取最新文章!

 

飞越面试官(三)--JVM的更多相关文章

  1. 飞越面试官(二)--JUC

    大家好!我是本号唯一官方指定没头屑的小便--怕屁林. JUC是什么东西?我相信很多经验尚浅的小伙伴部分都会为之一懵,我也是,三个字母都会读,连在一起就不知道在说什么,其实如果把它的全称写出来,“jav ...

  2. 飞越面试官(一)--Java基础

    大家好!我是本公众号唯一官方指定没头屑的小便--怕屁林. 众所周知,现场面试(包括视频面试)多数时候是没有白板,也就是说,对于你的知识点.项目经验.过往经历和个人介绍等等,都是靠一张嘴.所以考虑到这个 ...

  3. 面试高峰期,如何应对面试官的jvm刁难,特写一篇jvm面经(第一部)

    已经进入三月份,正所谓金三银四,正是一年最好的招聘期,想必我的公号粉丝们一定有不少想要跳槽的吧,哈哈,/**偷偷告诉你们其实小编也准备跳槽*/(我要加个注释,被老板知道可就完蛋了),说到面试,想必大家 ...

  4. 面试官:JVM锁优化都优化了啥?

    从JDK1.6开始,JVM对锁进行了各种优化,目的就是为了在线程间更高效的共享数据和解决互斥同步的问题.从锁优化的话题开始,可以引申出很多考点面试题,比如锁优化的技术.各优化技术的细节.CAS实现原理 ...

  5. 【对线面试官】CountDownLatch和CyclicBarrier的区别

    <对线面试官>系列目前已经连载31篇啦,这是一个讲人话面试系列 [对线面试官]Java注解 [对线面试官]Java泛型 [对线面试官] Java NIO [对线面试官]Java反射 &am ...

  6. 【对线面试官】Kafka基础入门

    <对线面试官>系列目前已经连载33篇啦,这是一个讲人话面试系列 [对线面试官]Java注解 [对线面试官]Java泛型 [对线面试官] Java NIO [对线面试官]Java反射 &am ...

  7. JVM工作原理和特点(一些二逼的逼神面试官会问的问题)

    作为一种阅读的方式了解下jvm的工作原理 ps:(一些二逼的逼神面试官会问的问题) JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.exe来完毕,通过以下4步来完毕JVM环境. ...

  8. Java 面试知识点解析(三)——JVM篇

    前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大 ...

  9. 面试官:你说你熟悉jvm?那你讲一下并发的可达性分析

    这是why技术的第35篇原创文章 上面这张图是我还是北漂的时候,在鼓楼附近的胡同里面拍的. 那天刚刚下完雨,路过这个地方的时候,一瞬间就被这五颜六色的门板和自行车给吸引了,于是拍下了这张图片.看到这张 ...

随机推荐

  1. java启动RabbitMQ消息报异常解决办法

    启动SpringCloud微服务,RabbitMQ报如下异常: 2019-08-12 18:15:49.543 ERROR 53096 --- [68.252.131:5672] o.s.a.r.c. ...

  2. (九)DVWA之SQL Injection--SQLMap&Fiddler测试(High)

    一.测试需求分析 测试对象:DVWA漏洞系统--SQL Injection模块--ID提交功能 防御等级:High 测试目标:判断被测模块是否存在SQL注入漏洞,漏洞是否可利用,若可以则检测出对应的数 ...

  3. Redis学习笔记(十八) 集群(下)

    复制和故障转移 Redis集群中的节点分为主节点(master)和从节点(slave),其中主节点用于处理槽,而从节点则用于复制某个主节点,并在被复制 的主节点下线时,代替下线主节点继续处理命令请求. ...

  4. refs转发 React.forwardRef

    2020-04-01 refs转发 前几天刚总结完ref&DOM之间的关系,并且想通了3种ref的绑定方式 今天总结一下refs转发 这是react中一直困扰我的一个点 示例: 输入: wor ...

  5. [转] 理解TCP序列号(Sequence Number)和确认号(Acknowledgment Number)

    点击阅读原译文 原文见:http://packetlife.net/blog/2010/jun/7/understanding-tcp-sequence-acknowledgment-numbers/ ...

  6. [ARC060D] 最良表現

    题目   点这里看题目. 分析   由于 KMP 的失配数组有着天然的找循环节的功能,因此我们不难想到对原串进行两次 KMP ,一正一反.   可以发现如下的规律:   1. 原串无循环节,这个时候 ...

  7. 写一个通用的List集合导出excel的通用方法

    前几天要做一个数据导出Excel 我就打算写一个通用的. 这样一来用的时候也方便,数据主要是通过Orm取的List.这样写一个通用的刚好. public static void ListToExcel ...

  8. Python爬虫小白入门(一)入门介绍

    一.前言 你是不是在为想收集数据而不知道如何收集而着急? 你是不是在为想学习爬虫而找不到一个专门为小白写的教程而烦恼? Bingo! 你没有看错,这就是专门面向小白学习爬虫而写的!我会采用实例的方式, ...

  9. Java8新特性之函数式接口

    <Java 8 实战>学习笔记系列 定义 函数式接口只定义一个抽象方法,可以有多个默认方法 函数式接口的接口名上,会被@FunctionalInterface标注 作用 函数式接口的方法可 ...

  10. linux下操作memcache的操作命令

    1.连接memcache linux下一般使用telnet连接memcache服务 [root@localhost ~]# telnet 127.0.0.1 11266 Trying 127.0.0. ...