JVM学习之一 JMM(Java内存模型)

JVM简介

    JVM是Java虚拟机的简称,是Java的程序运行时的环境基础,是基于软件模拟计算机硬件环境为Java的class文件提供的运行时环境,每次启动java程序都会在系统中开启一个java进程。它隐藏了底层技术的复杂性与机器与操作系统的差异性,使得程序员不用注意底层的硬件差别而专注实现业务逻辑。因此,程序员编写的源代码java文件经过编译后生成class文件,class文件在不同的操作系统上由JVM翻译成对应平台的执行命令进行运算,从而实现跨平台运行,也就是java的一次编写处处运行。

   JMM即Java内存模型,代表了Java虚拟机在运行时的数据区域的构成,根据需要将数据存储在不同的内存中。虽然JVM会在程序运行时自动管理内存无需开发人员在代码编写过程中强制实现内存的分配和回收功能,但是了解其模型以及如何分配内存对于编写运行快速和避免内存泄露的程序却是至关重要的。下面我们开始学习java 虚拟机的运行时数据区域:

运行时的数据区域

    不同的数据区域用途不同,其创建的时间和销毁的时机也不尽相同。

    Program Counter Register(程序计数器)

    作用:记录当前线程执行的字节码的行号指示器。当线程正在执行一个java方法时,这个计数器记录的是当前线程正在执行的字节码指令的地址,如果是本地方法则记录值为空。线程的切换与恢复的时候会存储和读取该内存的值。

    大小:所占内存较小。

    OOM:规范中没有规定。

    所有性质:线程私有,随着线程的创建而创建,随着线程的销毁而销毁。

    Java Virtuar Machine Stacks(java虚拟机栈)

    作用:存储java方法执行时的数据。每个方法在执行的时候都会创建一个栈帧,用于存储局部变量表 操作数栈 动态链接 方法出口等信息。每个方法从调用到执行完成就是一个栈帧在虚拟机栈中的入栈和出栈。

    大小:小于堆内存

    OOM:线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可扩展,但是扩展后仍不能满足内存需要则抛出OOM。

    所有性质:线程私有,随着线程的创建而创建,随着线程的销毁而销毁。

    Native Method Stack(本地方法栈)

    作用:存储native方法执行时候的数据。

    OOM:与JVMS相同。

    所有性质:线程私有,随着线程的创建而创建,随着线程的销毁而销毁

    Java heap(堆)

    作用:存放对象实例,几乎所有的对象实例都在这里分配。虚拟机规范中描述的是所有的对象实例及数组都要在堆上分配,但是随着技术的发展这也不是绝对的了。这也是垃圾收集器管理的主要内存,因此也被称为“GC堆"。可以细分为新生代和老年代,新生代又可进一步细分为Eden空间,From Survivor空间和To Survivor空间。

    大小:占了虚拟机内存的主要部分。

    OOM:当无法完成实例内存分配并且无法扩展时会抛出OOM

    所有性质:所有线程共享

    Method Area(方法区)

    作用:存储虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。不同的虚拟机对于是否实现内存回收不尽相同,也允许配置是否自动内存回收,即使自动回收效果也不甚理想。Runtime Constant Pool (运行时常量池)是方法区的一部分,用于存放编译期间生成的各种字面量和符号引用,由于规范中没有做具体的要求,不同的厂商有不同的实现。

    大小:小

    OOM:无法完成内存分配则抛出OOM。

    所有性质:所有线程共享。

以上是对于虚拟机在运行时内存模型的简单介绍,此外还有需要提及的是另外一块并非运行时的内存当然也不是规范中定义的内存区域,直接内存。JDK1.4新加入的NIO类,是引入的一种基于通道与缓冲区的I/O方式,它可以直接使用Native函数库直接分配堆外内存,然后通过DirectByteBuffer对象作为引用操作该内存,可以在在一些场景显著提高性能。在通过-Xmx分配内存时需要考虑此部分内存。


声明:本博客参考了周志明所著的《深入理解Java虚拟机》第二版



    

猜你喜欢

转载自blog.csdn.net/tony_java_2017/article/details/80460658