面试【JAVA基础】JVM


1、内存模型

1.1、堆
  1. 堆是所有线程共享的,主要存放对象实例和数组。
  2. 新生代和老年代的比例是1:2。
  3. 新生代中三个区域的比例是 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、老年代
  1. 大对象,需要大量连续内存空间的对象
  2. 长期存活的对象,对象年龄超过15(默认值)
  3. yong gc后survivor区容不下的对象。
1.2、JVM栈

线程私有的,每个线程都有一个栈,主要存放当前线程的局部变量,程序运行状态,方法返回值,方法出口等。

1.3、本地方法栈

为虚拟机使用到的native方法服务。

1.4、方法区

用于存放已经被夹在的类信息,常量,静态变量,1.8后取消了永久代,增加了元空间,元空间并不在虚拟机中,而是用的是本地内存。元空间中存放类的元信息,静态变量和常量池移入堆中。

1.5、程序计数器
  1. 程序私有,生命周期与程序相同
  2. 当前线程所执行的字节码的行号指示器。
  3. 用来实现分支,循环,跳转,异常等功能。

2、常量池中包括什么

常量池在编译时期确定,存放在编译生成的class文件中,包含了基本数据类型和对象类型(String和数组)

3、如何判断对象是否存活

使用什么方法标记一个对象可回收?

  1. 引用计数法,每个对象都有一个引用计数器,被引用 1 当引用数为0即为可被GC的对象
  2. 可达性分析:从根节点出发,向下搜索,未访问到的对象标记为不可达,可被回收

4、哪些对象可以用为GC ROOT对象

  1. 虚拟机栈中引用的对象。
  2. 方法区中静态对象引用的对象。
  3. 方法区中常量引用的对象。
  4. 本地方法栈中引用的对象。

5、GC策略

  1. 标记清除法,从根节点进行扫描,对存活的对象进行标记,标记完成后,再扫描整个空间中未被标记的对象,进行清理。容易造成内存碎片
  2. 复制,将内存划分为两份,当其中一份内存满了时,从根节点扫描,将存活的对象复制到另一份内存中。不会出现内存碎片问题,但需要两倍的空间。
  3. 标记整理,如标记清除法一样,标记对象,清除后将所有存活对象向左移。避免了内存碎片和两倍空间的问题,但增加了移动对象的成本。

6、具体GC收集器

  1. 串行垃圾收集器,serial
  2. 并行垃圾收集器 parNew,parallel 注重吞吐量
  3. cms 注重最短回收停顿时间
  4. G1

cms和G1的区别 :

  • cms是新生代的垃圾收集器,采用标记清除。
  • G1是新生代和老年代的垃圾收集器,采用标记整理。
  • cms会产生内存碎片,G1并不会。
  • Cms追求最小停顿时间,G1是达到可控的停顿时间,尽可能提高吞吐量。

7、什么样的对象进入老年代

  1. 大对象,需要大量连续内存空间的对象。
  2. 长期存活的对象,对象年龄超过15(默认值)。
  3. yong Gc后survivor区容不下的对象。

8、为什么要区分新生代和老年代

  1. 对象的生存情况不同使用不同的GC算法。
  2. 新生代对象可能被频繁的创建和回收,老年代回收较少。

9、survivor区存在的意义

  1. 为了提高对象进入老年代的门槛,减少fullGC的次数,因为fullGC很耗时。
  2. 两个survivor的作用是为了减少survivor区的内存碎片。

10、什么是yangGC

对年轻代进行gc。触发条件:

  1. eden区不足

    • 清空eden from to中没被引用的对象。
    • 将eden from中存活的对象 复制到 to中。
    • 将to中的对象晋升到old中,包括两类对象,一个是年龄到达阈值,一个是to中放不下。
  2. full gc也会出发yong gc

11、什么时候触发fullGC

  1. 手动触发的GC。
  2. 老年代的空间不足。
  3. 永久代的空间满了(方法区)。
  4. 统计到yong gc晋升到老年代的平均大小大于老年代剩余的大小(老年代的空间不足)。
  5. jvm自身固定频率的fullGC(默认一小时执行一次)。

12、内存的配置参数

  1. xms xmx 配置堆内存的最小和最大值
  2. xmn 年轻代内存的初始大小
  3. xss jvm栈大小

13、对象分配内存的两种方式

  1. 指针碰撞,如果内存对象是规整的,采用指针碰撞来为对象分配内存,所有使用过的内存在指针的一侧,未使用过的内存在指针的另一侧,分配内存只需要移动指针即可。
  2. 空闲列表,内存不规整,使用过的内存和未使用过的内存交织在一起,维护一个内存使用列表,记录那些内存是可用的,在分配的时候找到一块足够大的空间划分给对象,并更新列表上的内容。

14、如何减少GC的开销

  1. 避免显示的调用System.gc。
  2. 尽量减少临时对象的使用。
  3. 对象不使用时,最好显式的置为null。
  4. 尽量使用StringBuffer而不用String累加字符串。
  5. 能用基本类型就是用基本类型。
  6. 尽量少用静态对象变量。

15、什么是JAVA内存模型(JMM)

用于屏蔽掉各种硬件和操作系统的内存访问差异,以实现让java程序在各个平台下都能达到一致的并发效果。

16、什么时happens-before

  1. 保证了内存的可见性
  2. 制定了四个规则:
  • 程序顺序规则:一个线程中的每个操作 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产生的内存溢出及解决办法

  1. java heap space
    代码中存在大对象的分配,多次GC后仍找不到分配空间。
    解决办法:查看是否有大对象分配尤其是大数组。通过jmap把堆内存的日志dump下来,分析日志,如果解决不了增加堆内存的空间。
  2. permspace metaspace
    永久代或元空间溢出。生成大量的代理类或者使用自定义的类加载器。
    解决办法:查看有没有配置永久代或者元空间的大小。是否长时间没有重启jvm,是否有大量的反射操作。

原文地址:https://www.cnblogs.com/clawhub/p/12064453.html

时间: 2024-08-30 15:00:47

面试【JAVA基础】JVM的相关文章

java基础---JVM内存管理以及内存运行机制学习总结

自己从网上搜资料拼接了一张JVM内存图:如下图所示: 我们思考几个问题: 1.jVM是怎么运行的? 2.JVM运行时内存是怎么分配的? 3.我们写的java代码(类,对象,方法,常量,变量等等)最终存放在哪个区? VM运行时数据区域: 1.程序计数器(program Counter Register):   是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的 方式去实 现),字节码解释器工作时就是通过改

细节!重点!易错点!--面试java基础篇(二)

今天来给大家分享一下java的重点易错点第二部分,也是各位同学面试需要准备的,欢迎大家交流指正. 1.字符串创建与存储机制:当创建一个字符串时,首先会在常量池中查找是否已经有相同的字符串被定义,其判断的依据是String类型equals的返回值,若已经定义,则直接获取对其的引用.此时不需要创建新的对象,如果没有定义,首先创建这个对象,然后把它加入到字符串池中,再将它的引用返回.(例:new String(”aaa“)可能创建了1个或者2个对象,如果常量池中原来有aaa那么之创建了一个对象,如果没

细节!重点!易错点!--面试java基础篇(一)

今天来给大家分享一下java的重点易错点部分,也是各位同学面试需要准备的,欢迎大家交流指正. 1.java中的main方法是静态方法,即方法中的代码是存储在静态存储区的. 2.任何静态代码块都会在main方法之前执行. 3.java程序的初始化顺序:原则:静态优先于非静态,且只初始化一次:父类优先于子类:按照成员定义顺序初始化.例顺序:父类静态变量,父类静态代码块,子类静态变量,子类静态代码块,父类非静态变量,父类非静态代码块,父类构造函数,子类非静态变量,子类非静态代码块,子类构造函数. 4.

Java基础-JVM内存回收

Sun的JVMGenerationalCollecting(垃圾回收)原理是这样的:把对象分为年青代(Young).年老代(Tenured).持久代(Perm),对不同生命周期的对象使用不同的算法.(基于对对象生命周期分析) 1.Young(年轻代) 年轻代分三个区.一个Eden区,两个Survivor区.大部分对象在Eden区中生成.当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这

Java基础-JVM

jvm=> java虚拟机 一.java虚拟机的生命周期: Java虚拟机的生命周期 一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序.程序开始执行时他才运行,程序结束时他就停止.你在同一台机器上运行三个程序,就会有三个运行中的Java虚拟机. Java虚拟机总是开始于一个main()方法,这个方法必须是公有.返回void.直接受一个字符串数组.在程序执行时,你必须给Java虚拟机指明这个包换main()方法的类名. Main()方法是程序的起点,他被执行的线程初始化为程序的初始线

Java基础-JVM类加载机制

JVM的类加载是通过ClassLoader及其子类来完成的,类的层次关系和加载顺序可以由下图来描述: 1)Bootstrap ClassLoader /启动类加载器 $JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类  2)Extension ClassLoader/扩展类加载器 负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包 3

Java基础-JVM堆与栈

java内存分区      运行时数据区即是java内存,而且数据区要存储的东西比较多,如果不对这块内存区域进行划分管理,会显得比较杂乱无章.程序喜欢有规律的东西,最讨厌杂乱无章的东西. 根据存储数据的不同,java内存通常被划分为5个区域:程序计数器(Program Count Register).本地方法栈(Native Stack).方法区(Methon Area).栈(Stack).堆(Heap). 程序计数器(Program Count Register) 又叫程序寄存器.JVM支持多

Java基础——JVM内存结构

一.内存结构图 程序计数器 保存着当前线程执行的虚拟机字节码指令的内存地址,使得保证线程切换回来后,还能恢复到原先状态.(本地native丰富则计数器为空) 虚拟机栈(JVM栈) 每创建一个线程时就会对应创建一个Java栈,所以Java栈也是"线程私有"的内存区域,这个栈中又会对应包含多个栈帧,每调用一个方法时就会往栈中创建并压入一个栈帧,栈帧是用来存储方法数据和部分过程结果的数据结构,每一个方法从调用到最终返回结果的过程,就对应一个栈帧从入栈到出栈的过程. 我们平时说的堆栈堆栈,栈就

Java 基础入门

Java基础 JVM.JDK.JRE三者的关系: JDK:(Java Develop Kit)主要是针对开发人员使用的,是整个java的核心.它包括了Java运行环境(JRE),Java工具( javac/java/jdb等 )和Java基础类库. JRE:(Java Runtime Environment)是运行java程序必须的环境的集合.它包括了JVM标准实现和Java核心类库. JVM:(Java Virtual Machine)java虚拟机,java本身不跨平台,java跨平台是依靠

关于Java面试知识点解析——JVM基础篇

跳槽时时刻刻都在发生,但是我建议大家跳槽之前,先想清楚为什么要跳槽.切不可跟风,看到同事一个个都走了,自己也盲目的开始面试起来(期间也没有准备充分),到底是因为技术原因(影响自己的发展,偏移自己规划的轨迹),还是钱给少了,不受重视. 准备不充分的面试,完全是浪费时间,更是对自己的不负责(如果title很高,当我没说).今天给大家分享下 Java面试知识点解析--JVM基础篇 1)Java 是如何实现跨平台的? 注意:跨平台的是 Java 程序,而不是 JVM.JVM 是用 C/C++ 开发的,是