《JVM由浅入深学习【四】 》JVM由简入深学习提升分享

简介: 《JVM由浅入深学习【四】 》JVM由简入深学习提升分享

1.JVM中java堆的特点及作用

  • 是线程共享的一块区域
  • 虚拟机启动时就创建了
  • 是虚拟机中内存占用很大的一块
  • 存放所有的实例对象和数组
  • GC主要的作用区域
  • 可分为新生代(刚创建)和老年代(存活很久)
  • 新生代更细化可分为Eden,From Survivor,To Survivor,比例为8:1:1
  • 可以通过-Xms,-Xmx调节堆大小
  • 如果从分配内存的角度看,所有线程共享的 Java 堆中可以划分出多个线程私有的分配缓冲区 (Thread Local Allocation Buffer,TLAB) ,以提升对象分配时的效率
  • 无法在拓展:java.lang.OutOfMemoryError: Java heap space
    例子:模拟OOM,设置JVM参数-Xmx128m -Xms128m,这里最大最小都设置128M,我的Customer里面有个bytes变量,一个就有1m,所以每个CUstomer都多于1M,所以运行程序customerList长度到达一定次数就OOM了
@Data
public class Customer {
    private int no;
    private String username;
    private BigDecimal money;
    private byte[] a = new byte[1024 * 1024]; // 这里1024*1024byte等于1m
}
public class MyTestOOM {
    public static void main(String[] args) {
        List<Customer> customerList = new ArrayList<>();
        while (true) {
            Customer customer = new Customer();
            customer.setNo(1);
            customer.setUsername("testOOM");
            customer.setMoney(new BigDecimal("1000"));
            customerList.add(customer);
            System.out.println(customerList.size());
        }
    }
}

2. JVM中对象如何在堆内存中分配

  1. 指针碰撞(Bump The Poniter):内存规整的情况下
  2. 空闲列表(Free List):内存不规整的情况下
    以上两种方式要看垃圾回收器是否有空间压缩整理的能力来决定
  • 例如Serial,ParNew有有带压缩整理能力的收集器,则采用的是指针碰撞,简单高效
  • 例如CMS这种基于清除(Sweep)算法的收集器时,理论上采用较为复杂的空间列表分配方式
  1. 本地线程分配缓冲(TLAB):对象创建在虚拟机中频繁发生,即使仅仅修改一个指针所指向的位置,在并发情况下也并不是线程安全的,可能出现正在给对象 A分配内存,指针还没来得及修改,对象 B 又同时使用了原来的指针来分配内存的情况;
    两种解决方案
  • 同步锁定:JVM 是采用 CAS 配上失败重试的方式保证更新操作的原予性,
  • 线程锁定:把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在 Java堆中预先分配一小块内存,称为本地线程分配缓冲(Thread Local Allocation Buffer,TLAB),哪个线程要分配内存,就在哪个线程的本地缓冲区中分配,只有本地缓冲区用完了,分配新的缓存区时才需要同步锁定,虚拟机是否使用TLAB,可以通过-XX: +/-UseTLAB 参数来设定,-XX:TLABSize=512k设置大小


    java -XX:+PrintFlagsFinal来打印信息,可找到TLAB,默认开启,自动分配容量

3. JVM堆内存中的对象布局

  • 在 HotSpot 虚拟机中,一个对象的存储结构分为 3 块区域: 对象头(Header)、:实例数据(Instance Data) 和 对齐填充(Padding)
  • 对象头(Header): 包含两部分,
  • 第一部分用于存储对象自身的运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等,32 位虚拟机占 32 bit.64 位虚拟机占 64 bit,官方称为 “Mark Word’
  • 第二部分是类型指针,即对象指向它的类的元数据指针,虚拟机通过这个指针确定这个对象是哪个类的实例,另外,如果是Java 数组,对象头中还必须有一块用于记录数组长度的数据因为普通对象可以通过 Java 对象元数据确定大小,而数组对象不可以;
  • 实例数据(Instance Data): 程代码中所定义的各种成员变量类型的字段内容(包含父类继承下来的和子类中定义的);
  • 对齐填充(Padding): 不是必然需要,主要是占位,保证对象大小是某个字节的整数倍,HotSpot 虚拟机,任何对象的大小都是 8 字节的整数倍。如果不是整数倍就靠这个填充
相关文章
|
1月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
65 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
1月前
|
存储 SQL 小程序
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
这篇文章详细介绍了Java虚拟机(JVM)的运行时数据区域和JVM指令集,包括程序计数器、虚拟机栈、本地方法栈、直接内存、方法区和堆,以及栈帧的组成部分和执行流程。
31 2
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
|
1月前
|
Java 应用服务中间件 程序员
JVM知识体系学习八:OOM的案例(承接上篇博文,可以作为面试中的案例)
这篇文章通过多个案例深入探讨了Java虚拟机(JVM)中的内存溢出问题,涵盖了堆内存、方法区、直接内存和栈内存溢出的原因、诊断方法和解决方案,并讨论了不同JDK版本垃圾回收器的变化。
30 4
|
1月前
|
Arthas 监控 Java
JVM知识体系学习七:了解JVM常用命令行参数、GC日志详解、调优三大方面(JVM规划和预调优、优化JVM环境、JVM运行出现的各种问题)、Arthas
这篇文章全面介绍了JVM的命令行参数、GC日志分析以及性能调优的各个方面,包括监控工具使用和实际案例分析。
43 3
|
1月前
|
SQL 缓存 Java
JVM知识体系学习三:class文件初始化过程、硬件层数据一致性(硬件层)、缓存行、指令乱序执行问题、如何保证不乱序(volatile等)
这篇文章详细介绍了JVM中类文件的初始化过程、硬件层面的数据一致性问题、缓存行和伪共享、指令乱序执行问题,以及如何通过`volatile`关键字和`synchronized`关键字来保证数据的有序性和可见性。
29 3
|
1月前
|
缓存 前端开发 Java
JVM知识体系学习二:ClassLoader 类加载器、类加载器层次、类过载过程之双亲委派机制、类加载范围、自定义类加载器、编译器、懒加载模式、打破双亲委派机制
这篇文章详细介绍了JVM中ClassLoader的工作原理,包括类加载器的层次结构、双亲委派机制、类加载过程、自定义类加载器的实现,以及如何打破双亲委派机制来实现热部署等功能。
42 3
|
1月前
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
53 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
|
1月前
|
存储 安全 Java
jvm 锁的 膨胀过程?锁内存怎么变化的
【10月更文挑战第3天】在Java虚拟机(JVM)中,`synchronized`关键字用于实现同步,确保多个线程在访问共享资源时的一致性和线程安全。JVM对`synchronized`进行了优化,以适应不同的竞争场景,这种优化主要体现在锁的膨胀过程,即从偏向锁到轻量级锁,再到重量级锁的转变。下面我们将详细介绍这一过程以及锁在内存中的变化。
37 4
|
8天前
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。
|
6天前
|
Java Linux Windows
JVM内存
首先JVM内存限制于实际的最大物理内存,假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系。简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制。
8 1