JVM运行时内存区是如何划分的?

方法区(Method Area):存储类的字节码信息、常量池

堆区(Heap  Area):存储对象

Java方法栈(Stack Area):所有方法运行时,会创建一个栈帧对象,然后进入栈(方法栈)

本地方法栈(Native Method Stack Area):用C语言写的,方法执行时候,会进入本地方法栈

程序计数器(Pc Register):用于记录当前线程要执行的下一条字节码指定的地址

如何理解方法区(Method Area)?

方法区是逻辑一种定义,是一种规范,可被所有线程共享,不同JVM对方法区的落地实现可能不同,例如在JDK7中方法区称之为持久代,在JDK8中方法区叫元空间(Metaspace),并且这个元空间可以是JVM堆外的一块内存,不占用操作系统为JVM分配的内存。

如何理解JAVA中的堆(Heap),他的构成是怎样的?

Java中的堆是用于存储对象的一块区域,可被所有线程所共享。这块区域又可以分为年轻代和老年代,年轻代又分为伊甸园区和2个幸存区(有一块区域始终是空的)。

JVM虚拟机栈的结构是怎样的?

Java中每个线程都有一个虚拟机栈(Java方法栈)每个方法的执行都会对应着一次入栈(Push)和出栈(Pop)操作,栈中的元素为一个一个的栈帧(Stack Frame)对象,这个栈帧的构成主要有如下几部分:

1、操作数栈(用于执行运算)

2、局部变量表(用于存储方法内部的局部变量)

3、方法的返回值(存储方法的返回值)

4、动态链接(方法中要访问的一些常用池数据,要调用的方法,都会对应一个链接)

5、其他信息

如何理解程序计数器?

程序计数器用于记录当前线程要执行的下一条指令的偏移量地址,每个线程都有一个程序计数器,这个程序计数器也是所有内存中唯一一个不会出现内存溢出的区域

Java对象分配内存的一个基本过程是怎样的?

1、编译器通过逃逸分析(JDK8已默认开启)判定对象是在堆上分配还是在栈上分配

2、假如确定是在堆上分析,则可首先选择TLAB区,检测这块区域是否可以存储这个对象,可以则存储

3、假如TLAB区无法存储新创建的对象,则可以考虑在TLAB区之外的Eden区加锁分配(这里为什么加锁分配:申请分配内存的时候,有可能在java堆的同一个位置申请,这时就需要对拟分配的内存区域进行加锁或者采用CAS等操作,保证这个区域只能分配给一个线程)

4、如果Eden区无法存储对象,则执行Young GC(Minor)-年轻代的垃圾回收

5、假如Eden区执行了Young GC之后,仍然不足以存储对象,则直接分配到老年代。

6、假如老年代也不足以存储这个对象,则执行Full GC,这个过后还不能存储对象则抛出异常。

JVM中年轻代中幸存区设置的比例比较小,可能会产生什么问题?

年轻代的伊甸园区对象越来越多时,会启动Young GC,此时伊甸园区的对象就要拷贝到幸存区。假如这个幸存区比较小,无法存储从伊甸园区拷贝过来的幸存对象,此时这些对象就直接分配到老年代,就会导致老年代的对象越来越多,触发老年代GC的频率就变高,老年代的GC一般为Full GC,这个GC的时间会比较长,会影响系统的吞吐量和执行效率。说明:伊甸园区与两个幸存区的比例通常是8:1:1

假如伊甸园区设置的比例比较小,可能会出现什么问题?

我们创建的对象,大部分都是存储在伊甸园区。假如伊甸园区设置的比例小了,可能会增加GC频率。GC时,用户线程会出现短时间的暂停,这样会影响系统的执行性能。

JVM的堆内存为什么要分为年轻代和老年代?

通过分代设计,减少GC的空间范围,提高GC效率。

JVM调优中为什么推荐初始堆大小和最大堆大小要设置成一样的(-Xms2048m -Xms2048m)?

避免程序在运行过程中,因对象的多少或GC后内存的变化,进而导致的内存大小的调整,这个内存大小的调整的过程可能会带来更大的系统开销。(阿里的开发规范中)

 什么情况下对象可能会直接存储到老年代?

1、创建的对象比较大,年轻代没有空间存储这个对象。

2、年轻代GC时,活着对象比较多,幸存区存不下,此时这些对象可能会存储到老年代。

3、经过多次GC,没有被回收的对象,随着年龄的增加(默认是15)可能会移动到老年代。

Java中所有的对象都分配在堆上的,对吗?

随着技术的进步,这个说法已经不是那么准确了,对象可以分配在栈上了(小对象、未逃逸的对象可以分配在栈上)。

Java中的逃逸分析如何理解,可以解决什么问题?

逃逸分析本质是一种数据分析算法,基于这个算法判定对象是否发生了逃逸,未逃逸的对象可以直接分配在栈上、也可以执行标量替换。这样可以有效的减少对象在堆上的分配,进而减少阻塞、GC频率,提高执行效率。

如何理解Java中的标量替换技术,为什么要进行标量替换?

标量替换是一种将对象打散(将对象中成员以局部变量的方式进行设计)分配到栈上的技术,减少对象在堆中的创建次数,进而降低GC频率,提高其性能。

什么是内存溢出以及导致内存溢出的原因?

内存中剩余的内存空间不足以分配给新的内存请求,此时就会出现内存溢出。内存溢出可能会导致系统崩溃,具体可能导致内存溢出的原因有:

1、创建的对象太大。

2、创建的对象太多,又有大量的内存泄漏。

3、方法区的类太多了,没有足够的空间存储一些新的类型了。

4、方法出现了无限递归调用,可能会导致栈内存溢出。

什么是内存泄漏以及导致内存泄漏的原因?

程序中的对象在使用完毕之后,对象占有的内存空间,没有及时得到释放,一直占着内存空间,这个现象就称之为内存泄漏。常见的内存泄漏有:

1、缓存使用不当(例如缓存中对对象的引用都是强引用)。

2、内部类的使用不当(例如实例内存类会默认保存外部类引用)。

3、大量的IO连接操作没有及时得到关闭。

4、大量的使用static变量(这个的变量的生命周期不依赖于变量所在的类对象)。

Java中的四大引用有什么特点?

强引用:当内存不足时,JVM开始垃圾回收,对于强引用的对象,就算是出现了OOM也不会对该对象进行回收。强引用是我们最常见的普通对象引用,只要还有强引用指向一个对象 ,就能表明这个对象还“活着”,垃圾回收器就不会碰这些对象。

软引用:软引用是一种相对弱化了一些的引用,需要用 java.lang.ref.SoftReference 类来实现,可以让对象豁免一些垃圾收集。对于只有软引用(还有用、但非必须)的对象来说,

1)当系统内存充足时他不会被回收。

2)当系统内存不足时他会被回收。

这个特性很适合用来实现缓存:比如网页缓存、图片缓存等... 内存够用就保留,不够用就回收,可以很好地来解决OOM问题。

软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被JVM回收,这个软引用就会被加入到与之关联的引用队列中。

弱引用:弱引用也是用来描述非必须对象,但是他的强度比软引用更弱一些。

如果你创建了一个仅持有弱引用的对象,那么下一次垃圾回收发生的时候,无论当前内存是否足够,这个对象都会被回收掉。在JDK1.2之后提供了 WeakReference 类来实现弱引用。

虚引用:虚引用也称为幻像引用,他是最弱的一种引用。如果一个对象仅持有幻像引用,那么他就和没有任何引用一样。对其生存时间没有任何影响,我们也无法通过幻像引用来取得一个对象实例。事实上,我们可以通过为一个对象设置为幻像引用关联从而跟踪这个对象被垃圾回收的活动。在JDK1.2之后提供了 PhantomReference 类来实现弱引用。

引用队列:引用队列 ReferenceQueue 是用来配合引用工作的,最常与幻像引用一起使用,因为幻像引用的构造函数必须指定引用队列,而其他引用类型没有引用队列一样可以运行。

当某个被引用的对象被回收的时候,JVM会指向他的引用加入到引用队列的队列末尾,这相当于是一种通知机制。这个操作其实是由 ReferenceHandler 守护线程来做的,这个守护线程是在Reference静态代码块中建立并且运行的线程,所以只要Reference 这个父类被初始化,该线程就会创建和运行,他的运行方法依赖了比较多的本地(native)方法。由于ReferenceHandler 是守护线程,除非JVM进程终结,否则他会一直在后台运行。

不同引用类型的应用场景:

1)软引用的应用:断路器

2)弱引用的应用:ThreadLocal的ThreadLocalMap实现的

3)虚引用的应用:数据库连接池(数据库连接池 Connection Pool 应该具备的一个优点就是能够有效的避免连接资源泄露,同时能够对连接资源进行回收)

JVM运行时内存区的更多相关文章

  1. Java内存管理:Java内存区域 JVM运行时数据区

    转自:https://blog.csdn.net/tjiyu/article/details/53915869 下面我们详细了解Java内存区域:先说明JVM规范定义的JVM运行时分配的数据区有哪些, ...

  2. JVM运行时数据区与JVM堆内存模型小结

    前提 JVM运行时数据区和JVM内存模型是两回事,JVM内存模型指的是JVM堆内存模型. 那JVM运行时数据区又是什么? 它包括:程序计数器.虚拟机栈.本地方法栈.方法区.堆. 来看看它们都是干嘛的 ...

  3. JVM运行时数据区及对象在内存中初始化的过程

    JVM运行时数据区 Java虚拟机所管理的内存区域,也称为运行时数据区,分为以下几个运行时数据区,如图所示 程序计数器:当前程序所执行字节码的行号指示器 程序计数器(Program Counter R ...

  4. JVM 运行时内存结构

      1.JVM内存模型       JVM运行时内存=共享内存区+线程内存区 1).共享内存区       共享内存区=持久带+堆       持久带=方法区+其他       堆=Old Space ...

  5. JVM运行时内存结构

    原文转载自:http://my.oschina.net/sunchp/blog/369707 1.JVM内存模型 JVM运行时内存=共享内存区+线程内存区 1).共享内存区 共享内存区=持久带+堆 持 ...

  6. JVM运行时内存组成分为一些线程私

    JVM运行时内存组成分为一些线程私有的,其他的是线程共享的. 线程私有 程序计数器:当前线程所执行的字节码的行号指示器. Java虚拟机栈:java方法执行的内存模型,每个方法被执行时都会创建一个栈帧 ...

  7. Jvm运行时数据区

    一:运行时数据区 Java虚拟机在执行Java程序的过程中会把它管理的内存分为若干个不同的数据区域.这些区域有着各自的用途,一级创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户 ...

  8. JVM 运行时数据区 (三)

    JVM运行时数据区 运行时数据区由 程序计数器.java虚拟机栈.本地方法栈.堆.方法区 组成: 1.程序计数器 每一个Java线程都有一个程序计数器,用于保存程序执行到当前方法的哪一个指令,它是线程 ...

  9. JVM总结(一):概述--JVM运行时数据区

    大三下,趁着寒假重温一遍JVM,准备在一个系列来总价一下学习JVM的整个过程.争取在接下来的一个星期内更新完这一个系列,然后回家过年. JVM运行时数据区 线程私有的数据区 程序计数器 虚拟机栈 本地 ...

  10. [转]JVM运行时内存结构

    [转]http://www.cnblogs.com/dolphin0520/p/3783345.html 目录[-] 1.为什么会有年轻代 2.年轻代中的GC 3.一个对象的这一辈子 4.有关年轻代的 ...

随机推荐

  1. AIR32F103(九) CAN总线的通信和ID过滤机制及实例

    目录 AIR32F103(一) 合宙AIR32F103CBT6开发板上手报告 AIR32F103(二) Linux环境和LibOpenCM3项目模板 AIR32F103(三) Linux环境基于标准外 ...

  2. EMBARK研究: 依那西普治疗早期nr-axSpA达48周的临床和MRI疗效

    关键词: 放射学阴性中轴型SpA; TNF拮抗剂; 磁共振影像 EMBARK研究48周结果: 依那西普治疗早期放射学阴性中轴型SpA患者的临床与MRI疗效 电邮发布日期:2016年1月25日 文献: ...

  3. postgresql序列基本操作

    1.创建序列 CREATE SEQUENCE if not exists test_mergetable_id_seq INCREMENT 1 MINVALUE 1 MAXVALUE 99999999 ...

  4. Apache Maven Assembly自定义打包插件的使用

    前言 本文主要记录在SpringBoot项目中使用Apache Maven Assembly插件进行打包的相关内容: 官网说明:https://maven.apache.org/plugins/mav ...

  5. 图 -拓扑 topo

    https://www.cnblogs.com/New-ljx/p/13874648.html 在有向无环图上,用拓扑排序在O(n)的时间内求出最短/长路,是一个不错的选择(也称拓扑的DP). 只需要 ...

  6. No.2.6

    vw/vh:(能够使用vw单位设置网页元素的尺寸) 相对单位 相对视口的尺寸计算结果 vw:viewport width(1vw=1/100视口宽度) vh:viewport height(1vh=1 ...

  7. K8s集群调度

    k8s 调度器 Scheduler 是 kubernetes 的调度器,主要的任务是把定义的 pod 分配到集群的节点上.听起来非常简单,但有很多要考虑的问题: 公平:如何保证每个节点都能被分配资源 ...

  8. 从Encoder-Decoder(Seq2Seq)理解Attention的本质

    0. 目录 1. 前言 2. Transformer模型结构 2.1 Transformer的编码器解码器 2.2 输入层 2.3 位置向量 2.4 Attention模型 3. 总结 1. 语言模型 ...

  9. 一步一步地完成题目——费解的开关(C/C++语言)递推、递归、顺序思维

    前言 本文中博主将一步一步地.以正常人的顺序思维完成题目--费解的开关,使用的核心方法是递推与递归. 题目 参考题目:费解的开关 详细的题目信息相信大家都已经知道了,因此这里为了简洁只展示输入输出格式 ...

  10. java 内存锁

    import lombok.extern.slf4j.Slf4j;import java.util.Map;import java.util.concurrent.ConcurrentHashMap; ...