JVM总结(1)

1、运行时数据区域

Java虚拟机(Java Virtual Machine,简称JVM)在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束而建立和销毁。
在这里插入图片描述

2、程序计数器(Program Counter Register)
  • 线程私有,生命周期与线程相同
  • 当前线程所执行的字节码的行号指示器
  • 如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Natvie方法,这个计数器值则为空(undefined)
  • 程序计数器中存储的数据所占空间的大小不会随程序的执行而发生改变,所以此区域不会出现OutOfMemoryError的情况
3、Java虚拟机栈(JVM Stacks)
  • 线程私有,生命周期与线程相同
  • 虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程
  • 局部变量表存放了编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型);局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。
  • 该区域可能抛出以下异常:
    当线程请求的栈深度超过最大值,会抛出 StackOverflowError 异常;
    栈进行动态扩展时如果无法申请到足够内存,会抛出 OutOfMemoryError 异常。
4、本地方法栈(Native Method Stacks)
  • 与虚拟机栈非常相似,其区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native 方法服务。虚拟机规范中对本地方法栈中的方法使用的语言、使用方式与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。甚至有的虚拟机(譬如Sun HotSpot 虚拟机)直接就把本地方法栈和虚拟机栈合二为一。
  • 与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常

native关键字 说明java的作用范围达不到了,会去调用底层C语言的库 会进入本地方法栈 调用本地方法本地接口 JNI
JNI的作用:扩展java的使用,融合不同的编程语言为java所用 在内存区域中专门开辟一块的标记区域,即
本地方法栈,,登记native方法,在最终执行的时候,加载本地方法库中的方法通过JNI

栈:先进后出,后进先出
队列:先进先出

5、Java堆(Heap)
  • 被所有线程共享,在虚拟机启动时创建,用来存放对象实例,几乎所有的对象实例都在这里分配内存
  • 对于大多数应用来说,Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。
  • Java堆是垃圾收集器管理的主要区域,因此很多时候也被称做“GC堆”。如果从内存回收的角度看,由于现在收集器基本都是采用的分代收集算法,所以Java堆中还可以细分为:新生代和老年代;新生代又有Eden空间、From Survivor空间、To Survivor空间三部分。

一个JVM只有一个堆内存,堆内存的大小是可以调节的
类加载器读取类文件后,一般把扫描东西放到堆中 类、方法、常量、变量,保存我们所有引用类型的真实对象
堆内存分三个区域:新生区(幸存from区、幸存to区),老年区,永久区
GC垃圾回收,主要在新生区和老年区
当一个对象经历15次GC,都还没有回收,就会进入老年区
永久区也叫元空间:逻辑上存在,物理上不存在

*-Xms 设置初始化内存分配大小
-Xmx 设置最大分配内存
-XX:PrintGCDetails 打印GC垃圾回收信息
-XX:+HeapDumpOnOutOfMemoryError OOM
在 JDK1.7之前,HotSpot 使用永久代实现方法区;HotSpot 使用 GC 分代实现方法区带来了很大便利;

从 JDK1.7 开始HotSpot 开始移除永久代。其中符号引用(Symbols)被移动到 Native Heap中,字符串常量和类引用被移动到 Java Heap中。
在 JDK1.8 中,永久代已完全被元空间(Meatspace)所取代。元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。*

6、方法区(Method Area)
  • 用于存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
  • 和 Java 堆一样不需要连续的内存,并且可以动态扩展,动态扩展失败一样会抛出 OutOfMemoryError 异常。
  • 对这块区域进行垃圾回收的主要目标是对常量池的回收和对类的卸载,但是一般比较难实现,HotSpot 虚拟机把它当成永久代(Permanent Generation)来进行垃圾回收。
  • 方法区逻辑上属于堆的一部分,但是为了与堆进行区分,通常又叫“非堆”。
7、运行时常量池(Runtime Constant Pool)
  • 运行时常量池是方法区的一部分。
  • Class 文件中的常量池(编译器生成的各种字面量和符号引用)会在类加载后被放入这个区域。
  • 除了在编译期生成的常量,还允许动态生成,例如 String 类的 intern()。这部分常量也会被放入运行时常量池。
8、GC
  • 算法:引用计数法、复制算法(发生在新生区)、标记清除算法、分代
9、JMM
  • 缓存一致性协议,用于定义数据读写的规则;定义了线程工作内存的抽象关系,线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存
  • 解决共享对象的可见性问题:volilate
10、volilate
  • volatile关键字是用来修饰变量的:被volatile关键字修饰的变量会直接存储到主内存中。并且所有关于该变量的读操作,都会直接从主内存中读取,而不是直接从CPU缓存。

  • 通过 volatile 修饰的变量,所有关于该变量的读操作,都会直接从主内存中读取,而不是 CPU 自己的缓存。而所有该变量的写操都会写到主内存上

  • 可见性:1、修改本地内存,强制刷回主内存。2、强制让其他线程的工作内存失效过期。

  • 互斥性:同一时刻只允许一个线程操作 volatile 变量,volatile 修饰的变量在不加锁的场景下也能实现有锁的效果,类似于互斥锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值