乐趣区

关于jvm:JVM笔记1-运行时数据区

[TOC]

(一)java 内存区域治理

C/C++ 每一个 new 操作都须要本人去 delete/free,而 java 外面有虚拟机主动治理内存,不容易呈现内存透露或者溢出的问题,然而不容易呈现不代表不呈现,理解虚拟机怎么应用和治理内存是非常重要的是,对程序优化或者问题排查有帮忙。

运行时区域次要分为:

  • 线程公有:

    • 程序计数器:Program Count Register, 线程公有,没有垃圾回收
    • 虚拟机栈:VM Stack,线程公有,没有垃圾回收
    • 本地办法栈:Native Method Stack, 线程公有,没有垃圾回收
  • 线程共享:

    • 办法区:Method Area,以 HotSpot 为例,JDK1.8后元空间取代办法区,有垃圾回收。
    • 堆:Heap,垃圾回收最重要的中央。

1.1 程序计数器

空间很小,以后线程执行的字节码的行号指示器(线程独有,批示以后执行到哪,下一步须要执行哪一个字节码),分支,循环,跳转,异样解决,线程复原都须要依赖它。
线程公有:java多线程其实是线程轮流切换并调配处理器执行工夫的形式实现,一个核一个具体的工夫点,只会执行一个线程的指令。线程切换须要保留和复原正确的执行地位(爱护和复原现场),所以不同的线程须要不同的程序计数器。

  • 执行 java 办法时,程序计数器记录的是正在执行的字节码指令地址
  • 执行 Native 办法,程序计数器为空

惟一一个没有规定任何 OutOfMemory 的区域,也没有 GC(垃圾回收)。

1.2 虚拟机栈

线程公有,生命周期和线程一样,次要是记录该线程 Java 办法执行的内存模型。虚拟机栈外面放着好多栈帧。留神虚拟机栈,对应是 Java 办法,不包含本地办法。
一个 Java 办法执行会创立一个栈帧,一个栈帧次要存储:

  • 局部变量表
  • 操作数栈
  • 动静链接
  • 办法进口

每一个办法调用的时候,就相当于将一个栈帧放到虚拟机栈中(入栈),办法执行实现的时候,就是对应着将该栈帧从虚拟机栈中弹出(出栈)。

每一个线程有一个本人的虚拟机栈,这样就不会混起来,如果不是线程独立的话,会造成调用凌乱。

大家平时说的 java 内存分为堆和栈,其实就是为了简便的不太谨严的说法,他们说的栈个别是指虚拟机栈,或者虚拟机栈外面的局部变量表。

局部变量表个别寄存着以下数据:

  • 根本数据类型(boolean,byte,char,short,int,float,long,double
  • 对象援用(reference 类型,不肯定是对象自身,可能是一个对象起始地址的援用指针,或者一个代表对象的句柄,或者与对象相干的地位)
  • returAddress(指向了一条字节码指令的地址)

局部变量表内存大小编译期间确定,运行期间不会变动。空间掂量咱们叫 Slot(局部变量空间)。64 位的 long 和 double 会占用 2 个 Slot,其余的数据类型占用 1 个 Slot。

异样:

  • StackOverflowError:线程申请的栈深度大于虚拟机容许的深度
  • OutOfMemoryError:内存不足

1.3 本地办法栈

和虚拟机栈相似,对应本地办法,Native,虚拟机标准容许语言,应用形式和数据结构不同,有些可能将虚拟机栈和本地办法栈合并。
异样与虚拟机栈统一:

  • StackOverflowError:线程申请的栈深度大于虚拟机容许的深度
  • OutOfMemoryError:内存不足

1.4 java 堆

堆是内存治理最大的一块,线程共享。

虚拟机标准中说,所有的对象实例和数组都要在堆上调配。然而实际上 不是所有的对象都在堆上调配 ,这个和 JIT 编译器的倒退和逃逸剖析技术相干。Why?
// TODO
堆的细分:新生代,老年代,再细分有 Eden,From survivor,To survivor 等。

堆中也有可能有线程公有的区域,调配缓冲区。

物理上能够不间断,然而逻辑上是间断的。

异样:

  • OutOfMemoryError:内存不足

1.5 办法区

名为非堆,然而理论和堆一样,是线程共享的区域,次要存贮以下信息:

  • 已被虚拟机加载的类信息
  • 常量
  • 动态变量
  • 即时编译器编译后的代码

办法区不等于永恒代,批示 Hotspot 虚拟机将 GC 分代收集拓展到办法区,也就是用永恒代实现了办法区,而其余的虚拟机不肯定,不是固定的。JDK1.7 将永恒代的字符串常量移出了。

办法区回收垃圾的成果不是很好,能够抉择不回收,虚拟机能够决定,当然也可能产生内存透露。
异样:

  • OutOfMemoryError:内存调配异样

1.5.1 运行时常量池

运行时常量池时办法区的一部分,然而不是全副,Class文件次要包含:

  • 类的版本
  • 字段
  • 办法
  • 接口
  • 常量池,寄存编译产生的字面量和符号援用,个别除了形容 Class 文件的符号援用,还有间接援用也在外面。是动静的,运行时能够产生,比方 String.intern()办法。

异样:

  • OutOfMemoryError:内存调配异样

(二)间接内存

不是虚拟机运行时数据区,也不是标准规定的区域,然而应用频繁且可能会有 OutOfMemoryError:内存调配异样呈现。
比方,NIO(1.4)基于 Channel 与 Buffer 的 I /O,能够用 Native 函数间接调配堆外内存,通过存储在 Java 堆中的 DirectByteBuffer 对象作为援用来操作,进步性能,不须要 Java 堆和 Native 堆都来回复制数据。

间接内存受物理的内存,或者处理器寻址空间之类的限度。

本文系 JVM 学习相干笔记,整顿来自周志明老师的《深刻了解 Java 虚拟机》,无比钦佩,强烈推荐!

【作者简介】
秦怀,公众号【秦怀杂货店】作者,技术之路不在一时,山高水长,纵使迟缓,驰而不息。这个世界心愿所有都很快,更快,然而我心愿本人能走好每一步,写好每一篇文章,期待和你们一起交换。

此文章仅代表本人(本菜鸟)学习积攒记录,或者学习笔记,如有侵权,请分割作者核实删除。人无完人,文章也一样,文笔稚嫩,在下不才,勿喷,如果有谬误之处,还望指出,感激不尽~

退出移动版