面试【JAVA基础】JVM

1、内存模型
1.1、堆
- 堆是所有线程共享的,主要存放对象实例和数组。
- 新生代和老年代的比例是1:2。
- 新生代中三个区域的比例是 8 : 1 : 1。
1.1.1、新生代
对象分配在eden区中,当eden区满时会触发minor gc,将eden区中存活的对象,复制到survivor0区中,清空eden区,当survivor0中满了时,会将存活的对象复制到survivor1区中,然后将survivor0和survivor1交换,保持survivor1是空的。每经过一次yong gc 年龄就 1。
- Eden
对象创建,对象分配在eden区,当eden区满了,再创建对象的时候,会触发minor gc,进行Eden和from surivior区域的垃圾回收。 - FromServivor
- ToSurvivor
minor gc后还存活的对象会被放入此区域,当对象年龄到达阈值后会进入老年代。或者to surivior区域满了,会将对象放入老年代。
1.1.2、老年代
- 大对象,需要大量连续内存空间的对象
- 长期存活的对象,对象年龄超过15(默认值)
- yong gc后survivor区容不下的对象。
1.2、JVM栈
线程私有的,每个线程都有一个栈,主要存放当前线程的局部变量,程序运行状态,方法返回值,方法出口等。
1.3、本地方法栈
为虚拟机使用到的native方法服务。
1.4、方法区
用于存放已经被夹在的类信息,常量,静态变量,1.8后取消了永久代,增加了元空间,元空间并不在虚拟机中,而是用的是本地内存。元空间中存放类的元信息,静态变量和常量池移入堆中。
1.5、程序计数器
- 程序私有,生命周期与程序相同
- 当前线程所执行的字节码的行号指示器。
- 用来实现分支,循环,跳转,异常等功能。
2、常量池中包括什么
常量池在编译时期确定,存放在编译生成的class文件中,包含了基本数据类型和对象类型(String和数组)
3、如何判断对象是否存活
使用什么方法标记一个对象可回收?
- 引用计数法,每个对象都有一个引用计数器,被引用 1 当引用数为0即为可被GC的对象
- 可达性分析:从根节点出发,向下搜索,未访问到的对象标记为不可达,可被回收
4、哪些对象可以用为GC ROOT对象
- 虚拟机栈中引用的对象。
- 方法区中静态对象引用的对象。
- 方法区中常量引用的对象。
- 本地方法栈中引用的对象。
5、GC策略
- 标记清除法,从根节点进行扫描,对存活的对象进行标记,标记完成后,再扫描整个空间中未被标记的对象,进行清理。容易造成内存碎片
- 复制,将内存划分为两份,当其中一份内存满了时,从根节点扫描,将存活的对象复制到另一份内存中。不会出现内存碎片问题,但需要两倍的空间。
- 标记整理,如标记清除法一样,标记对象,清除后将所有存活对象向左移。避免了内存碎片和两倍空间的问题,但增加了移动对象的成本。
6、具体GC收集器
- 串行垃圾收集器,serial
- 并行垃圾收集器 parNew,parallel 注重吞吐量
- cms 注重最短回收停顿时间
- G1
cms和G1的区别 :
- cms是新生代的垃圾收集器,采用标记清除。
- G1是新生代和老年代的垃圾收集器,采用标记整理。
- cms会产生内存碎片,G1并不会。
- Cms追求最小停顿时间,G1是达到可控的停顿时间,尽可能提高吞吐量。
7、什么样的对象进入老年代
- 大对象,需要大量连续内存空间的对象。
- 长期存活的对象,对象年龄超过15(默认值)。
- yong Gc后survivor区容不下的对象。
8、为什么要区分新生代和老年代
- 对象的生存情况不同使用不同的GC算法。
- 新生代对象可能被频繁的创建和回收,老年代回收较少。
9、survivor区存在的意义
- 为了提高对象进入老年代的门槛,减少fullGC的次数,因为fullGC很耗时。
- 两个survivor的作用是为了减少survivor区的内存碎片。
10、什么是yangGC
对年轻代进行gc。触发条件:
- eden区不足
- 清空eden from to中没被引用的对象。
- 将eden from中存活的对象 复制到 to中。
- 将to中的对象晋升到old中,包括两类对象,一个是年龄到达阈值,一个是to中放不下。
- full gc也会出发yong gc
11、什么时候触发fullGC
- 手动触发的GC。
- 老年代的空间不足。
- 永久代的空间满了(方法区)。
- 统计到yong gc晋升到老年代的平均大小大于老年代剩余的大小(老年代的空间不足)。
- jvm自身固定频率的fullGC(默认一小时执行一次)。
12、内存的配置参数
- xms xmx 配置堆内存的最小和最大值
- xmn 年轻代内存的初始大小
- xss jvm栈大小
13、对象分配内存的两种方式
- 指针碰撞,如果内存对象是规整的,采用指针碰撞来为对象分配内存,所有使用过的内存在指针的一侧,未使用过的内存在指针的另一侧,分配内存只需要移动指针即可。
- 空闲列表,内存不规整,使用过的内存和未使用过的内存交织在一起,维护一个内存使用列表,记录那些内存是可用的,在分配的时候找到一块足够大的空间划分给对象,并更新列表上的内容。
14、如何减少GC的开销
- 避免显示的调用System.gc。
- 尽量减少临时对象的使用。
- 对象不使用时,最好显式的置为null。
- 尽量使用StringBuffer而不用String累加字符串。
- 能用基本类型就是用基本类型。
- 尽量少用静态对象变量。
15、什么是JAVA内存模型(JMM)
用于屏蔽掉各种硬件和操作系统的内存访问差异,以实现让java程序在各个平台下都能达到一致的并发效果。
16、什么时happens-before
- 保证了内存的可见性
- 制定了四个规则:
- 程序顺序规则:一个线程中的每个操作 happens-before 与后续的所有操作。
- 监视器锁规则:一个监视器解锁 happens-before 于 加锁。
- volatile变量规则: 写操作 happens-before 读操作。
- 传递性 A happens-before B ,B happens-before C ,那么Ahappens-before C。
17、性能调优工具
17.1、jps
jps主要用来输出jvm中运行的进程状态信息。
-l 输出main类或者jar的权限名。
17.2、jstack
jstack pid > log
可以将线程堆栈转存到文件中。
日志分析可以使用fastthread.io。
17.3、jstat
可以显示出虚拟机进程中的classloader、内存、gc等运行数据。
参数
-class pid 类加载统计。
-gc 垃圾回收统计 ,后面跟两个参数一个是间隔输出时间,一个是总共输出次数。
gc日志可以使用 gceasy.io
17.4、jmap
jmap查看堆内存的使用情况:
jmap pid
17.5、jinfo
查看java程序的运行环境参数:
jinfo pid
18、内存栅栏
通过确保从另一个CPU来看,屏障的两边的所有指令都是正确的程序顺序,而保持程序顺序的外部可见性;其次可以实现内存数据可见性,确保内存数据会同步到CPU缓存子系统。
19、JVM产生的内存溢出及解决办法
- java heap space
代码中存在大对象的分配,多次GC后仍找不到分配空间。
解决办法:查看是否有大对象分配尤其是大数组。通过jmap把堆内存的日志dump下来,分析日志,如果解决不了增加堆内存的空间。 - permspace metaspace
永久代或元空间溢出。生成大量的代理类或者使用自定义的类加载器。
解决办法:查看有没有配置永久代或者元空间的大小。是否长时间没有重启jvm,是否有大量的反射操作。

面试【JAVA基础】JVM的更多相关文章
- Java基础-JVM调优策略简介
Java基础-JVM调优策略简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.JVM结构分析 1>.JVM结构图 2>.JVM运行时数据区功能说明 JVM管理的内 ...
- 细节!重点!易错点!--面试java基础篇(二)
今天来给大家分享一下java的重点易错点第二部分,也是各位同学面试需要准备的,欢迎大家交流指正. 1.字符串创建与存储机制:当创建一个字符串时,首先会在常量池中查找是否已经有相同的字符串被定义,其判断 ...
- Java基础-JVM篇
1.1 .线程 这里所说的线程指程序执行过程中的一个线程实体.JVM 允许一个应用并发执行多个线程.Hotspot JVM 中的 Java 线程与原生操作系统线程有直接的映射关系.当线程本地存储. ...
- Java基础-JVM堆与栈
首先看一个解析列子 JVM的内存空间: (1). Heap 堆空间:分配对象 new Student() (2). Stack 栈空间:临时变量 Student stu (3).Code 代码区 :类 ...
- Java基础-JVM内存回收
Sun的JVMGenerationalCollecting(垃圾回收)原理是这样的:把对象分为年青代(Young).年老代(Tenured).持久代(Perm),对不同生命周期的对象使用不同的算法.( ...
- Java基础-JVM类加载机制
JVM的类加载是通过ClassLoader及其子类来完成的,类的层次关系和加载顺序可以由下图来描述: 1)Bootstrap ClassLoader /启动类加载器 $JAVA_HOME中jre/li ...
- Java基础-JVM
jvm=> java虚拟机 一.java虚拟机的生命周期: Java虚拟机的生命周期 一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序.程序开始执行时他才运行,程序结束时他就停止. ...
- 细节!重点!易错点!--面试java基础篇(一)
今天来给大家分享一下java的重点易错点部分,也是各位同学面试需要准备的,欢迎大家交流指正. 1.java中的main方法是静态方法,即方法中的代码是存储在静态存储区的. 2.任何静态代码块都会在ma ...
- Java基础——JVM内存结构
推荐阅读:https://www.cnblogs.com/wangjzh/p/5258254.html 一.内存结构图 先导知识: 一个 Java 源程序文件,会被编译为字节码文件(以 class 为 ...
- 面试----java基础集合---------------------comparable和comparator 的区别
comparable接口 是主要是用来自定义类存储在主要是TreeSet,TreeMap(键)集合中存储时,自定通过实现这种接口得到自然排序的功能. comparator 接口 是主要是用来 ...
随机推荐
- 小伙子自从学会用Python爬取岛国“动作”电影,身体一天不如一天
在互联网的世界里,正确的使用VPN看看外面的世界,多了解了解世界的发展.肉身翻墙后,感受一下外面的肮脏世界.墙内的朋友叫苦不迭,由于某些原因,VPN能用的越来越少.上周我的好朋友狗子和我哭诉说自己常用 ...
- Java连接Redis,存储对象获取对象()byte和json),连接池
Java连接Redis Jedis连接Redis,Lettuce连接Redis Jedis连接Redis 1. 创建maven项目 2. 引入依赖 <dependencies> <d ...
- [vue]子组件通过props获取父组件数据以及使用watch解决动态数据不生效问题
父子组件的传值,在Vue官方也写得很清楚,父组件中使用v-bind绑定传送,子组件使用props接收. 父组件通过v-bind绑定数据: <template> <router-vie ...
- STM32中 BOOT0 BOOT1设置(问题:程序下载进去但无法运行)
默认BOOT0接10K接地,BOOT1接10K接地 实际如果BOOT0不接10K到地,会导致程序能下载进去,但是无法运行情况
- 关于 JavaScript 字符串的一个小知识
说起字符串,我们再熟悉不过了.接触编程的第一个经典任务就是输出字符串:Hello, world.但是你知道 JavaScript 字符串在计算机里是怎么表示的吗? 最简单直观但不太准确的的理解就是,字 ...
- MQC集群配置错误
这个错误说明配置里面,MQC环境配置错了 运行war包时会读到本地的配置system-config.propertites文件
- 手动SQL注入总结
1.基于报错与union的注入 注意:union联合查询注入一般要配合其他注入使用 A.判断是否存在注入,注入是字符型还是数字型,有没过滤了关键字,可否绕过 a.如何判断是否存在注入 一般有一下几种 ...
- HotSpot的执行引擎-CallStub栈帧
之前多次提到接触到调用JavaCalls::call()方法来执行Java方法,如: (1)Java主类装载时,调用JavaCalls::call()方法执行的Java方法checkAndLoadMa ...
- unity探索者之socket传输protobuf字节流(四)
版权声明:本文为原创文章,转载请声明http://www.cnblogs.com/unityExplorer/p/7027659.html 上篇已经把socket的传输说的差不多了,这篇主要是说说断线 ...
- 全网最通透的Java8版本特性讲解
「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...