美文网首页
JVM内存管理

JVM内存管理

作者: 王多鱼2 | 来源:发表于2020-12-08 23:08 被阅读0次

    以下内容:并非作者自己总结,勿喷


    JVM.png

    android大概了解这些
    总结:JVM运行时数据区主要有 私有区域 java栈(先进后去,里面有N个栈帧) 本地栈(native栈), 程序计数器
    共享区域 方法区: 存放 类信息 常量 静态变量 即时编译期编译后的代码
    堆:new出来的对象

    一:JVM是什么?

    可以理解成只是一个翻译;
    它可以跨平台,跨语音; 各种语言编译成字节码,然后通过JVM运行到各种平台上;

    二:JVM的跨平台与语言无关性

    JVM的跨平台
    JVM的语言无关性

    跨平台性.png

    三:JVM的整体

    JVM的整体.png

    JVM的运行过程

    java文件 --》javac翻译,生成class文件,通过类加载器classLoader,JVM会把class加载到运行时数据区(内存),在通过执行引擎
    到操作系统上;

    JVM就是把字节码翻译成机器码

    四:什么是运行时数据区?

    Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域

    它有如下类型

    程序计数器、虚拟机栈、本地方法栈、Java堆、方法区(运行时常量池)、直接内存


    运行时数据区域.jpg
    • 1,白色部分就是线程私有的;
    • 2,灰色部分不受线程控制的,共享区域;

    线程私有区域

    4.1 程序计数器

    指向当前线程正在执行的字节码指令的地址

    记录某个线程当前程序运行到那个位置;如图

    4.1 .1:为什么需要这个程序计数器?

    答:JVM是个软件,有可能程序在跑的时候,cpu被切换出去了(时间轮转机制),无论单线程还是多线程,有可能程序被终止,这个时候需要记录程序运行到哪一行;

    4.1 .2:JVM内存区域中 唯一不会OOM ;

    答: 因为它要记录一个地址;

    运行内存区域.png

    4.2 虚拟机栈(JAVA栈)

    • 比较重要的一片区域;存储当前线程运行方法所需的数据,指令、返回地址;
    • 它具有先进后出的特点
    • 有大小限制

    4.2.1:什么是栈帧?

    • 虚拟机栈比喻成子弹夹,那栈帧就是子弹;一个方法对应一个栈帧;如图上面的 运行内存区域.png
    • 它包括:局部变量表, 操作数栈 , 动态连接, 完成出口

    java 解释执行是栈(操作数栈)兼容性好,效率偏低,c是寄存器(硬件运算)。移植性差

    4.3 本地方法栈(native区)

    本地方法栈保存的是native方法的信息,
    本地方法栈跟 Java 虚拟机栈的功能类似,Java 虚拟机栈用于管理 Java 函数的调用,而本地方法栈则用于管理本地方法的调用。但本地方法并不是用 Java 实现的,而是由 C 语言实现的。

    当一个JVM创建的线程调用native方法后,JVM不再为其在虚拟机栈中创建栈帧,JVM只是简单地动态链接并直接调用native方法

    虚拟机规范无强制规定,各版本虚拟机自由实现 HotSpot直接把本地方法栈和虚拟机栈合二为一

    线程共享的区域

    4.4方法区

    存放以下数据

    • 类信息
    • 常量
    • 静态变量
    • 即时编译期编译后的代码

    4.4 堆(java堆)

    • 对象实例(几乎所有)
    • 数组

    Java堆的大小参数设置

    -Xmx 堆区内存可被分配的最大上限
    -Xms 堆区内存初始内存分配的大小

    4.4:为什么共享区域不共用一个区域要分方法区和堆?

    堆:对象和数组,频繁的回收;

    直接内存

    不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域;如果使用了NIO,这块区域会被频繁使用,在java堆内可以用directByteBuffer对象直接引用并操作;
    这块内存不受java堆大小限制,但受本机总内存的限制,可以通过-XX:MaxDirectMemorySize来设置(默认与堆内存最大值一样),所以也会出现OOM异常。

    五:从底层深入理解运行时数据区

    image.png

    上面代码内存分布图如下:


    image.png

    六:深入辨析堆和栈

    功能角度:

    • 以栈帧的方式存储方法调用的过程,并存储方法调用过程中基本数据类型的变量(int、short、long、byte、float、double、boolean、char等)以及对象的引用变量,其内存分配在栈上,变量出了作用域就会自动释放;
    • 而堆内存用来存储Java中的对象。无论是成员变量,局部变量,还是类变量,它们指向的对象都存储在堆内存中;

    线程独享还是共享:

    • 栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可以理解成线程的私有内存。
    • 堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问。

    空间大小

    栈的内存要远远小于堆内存

    六:内存溢出

    • 栈溢出
      StackOverflowError 递归容易出现

    • 堆溢出
      内存溢出:申请内存空间,超出最大堆内存空间。
      如果是内存溢出,则通过 调大 -Xms,-Xmx参数。
      如果不是内存泄漏,就是说内存中的对象却是都是必须存活的,那么久应该检查JVM的堆参数设置,与机器的内存对比,看是否还有可以调整的空间,再从代码上检查是否存在某些对象生命周期过长、持有状态时间过长、存储结构设计不合理等情况,尽量减少程序运行时的内存消耗。

    • 方法区溢出
      (1) 运行时常量池溢出
      (2)方法区中保存的Class对象没有被及时回收掉或者Class信息占用的内存超过了我们配置。

    • 本机直接内存溢出
      直接内存的容量可以通过MaxDirectMemorySize来设置(默认与堆内存最大值一样),所以也会出现OOM异常;
      由直接内存导致的内存溢出,一个比较明显的特征是在HeapDump文件中不会看见有什么明显的异常情况,如果发生了OOM,同时Dump文件很小,可以考虑重点排查下直接内存方面的原因。

    七:虚拟机优化技术

    编译优化技术——方法内联

    image.png

    方法内联的优化行为,就是把目标方法的代码原封不动的“复制”到调用的方法中,避免真实的方法调用而已。

    栈的优化技术——栈帧之间数据的共享

    在一般的模型中,两个不同的栈帧的内存区域是独立的,但是大部分的JVM在实现中会进行一些优化,使得两个栈帧出现一部分重叠。(主要体现在方法中有参数传递的情况),让下面栈帧的操作数栈和上面栈帧的部分局部变量重叠在一起,这样做不但节约了一部分空间,更加重要的是在进行方法调用时就可以直接公用一部分数据,无需进行额外的参数复制传递了。


    image.png

    相关文章

      网友评论

          本文标题:JVM内存管理

          本文链接:https://www.haomeiwen.com/subject/plexgktx.html