深入理解JVM(1)——JVM内存模型
Java虚拟机的内存空间分为五个部分,分别是:
- 程序计数器;
- Java虚拟机栈
- 本地方法栈
- 堆
- 方法区
接下来对这五部分分别进行详细的介绍
1、程序计数器:
a)什么是程序计数器:程序计数器是内存中的一个很小的空间,可以看作是当前线程正在执行的字节码的行号指示器。也就是说,程序计数器里面记录的是当前线程正在执行的字节码指令的地址。需要注意的是:如果当前线程正在执行的是一个本地方法,那么此时程序计数器为空。
b) 程序计数器的作用:字节码解释器通过改变程序计数器依次读取指令,实现程序的流程控制;在多线程的情况下,程序计数器用来记录当前线程的执行位置,以便于当线程被切回来的时候能够记住该线程上次运行到那里了。
c) 程序计数器的特点:是一块较小的内存空间;线程私有,每一个线程都有一个程序计数器;是唯一一个不会出现OutOfMemoryError的区域;生命周期随着线程的创建而创建,线程的结束而死亡。
2、Java虚拟机栈
a) 什么是Java虚拟机栈:Java虚拟机栈是描述Java方法运行过程的内存模型。Java虚拟机会为每一个即将运行的java方法创建一个叫“栈帧”的区域,该区域用来存放Java方法运行过程中需要的一些信息,这些信息主要包括:局部变量表、操作数栈、动态链接、方法出口信息等。
注意:当方法在运行过程中需要创建局部变量的时,就会将变量的值存入局部变量表中。人们常说的Java内存空间分为“栈”和“堆”,栈中存放的是局部变量,堆中存放的是对象,这句话是不完全正确的,几乎所有的对象都是存放在堆中,但是Java虚拟机会为每一个Java方法创建一个“栈帧”,其中栈帧包括局部变量表,但还包括其他的如操作数栈、动态链接和方法出口信息等。
b)Java虚拟机栈的主要特点:
1) 局部变量表的创建是在Java方法即将运行的时候随着栈帧的创建而创建,但是局部变量表的大小是在编译阶段就已经确定的,创建的时候只是按照实现分配好的大小进行创建,而且在Java方法运行的过程中局部变量表的大小不会改变。
2)Java虚拟机栈是线程私有的,每个线程都有自己的Java虚拟机栈,并且随着线程的创建而创建,随着线程的结束而死亡。
3) Java虚拟机栈一般会出现两种错误:StackOverFloeError和OutOfMemoryError。
若Java虚拟机栈的内存大小不允许动态扩展,那么当线程请求栈的深度超过当前Java虚拟机栈的最大深度的时候,就抛出StackOverFlowError异常。StackOverFlowError表示当前线程申请的栈超过了事先定好的栈的最大深度,但内存空间可能还有很多。
若Java虚拟机栈的内存大小允许动态扩展,且当线程请求栈时内存用完了,无法再动态扩展了,此时抛出OutOfMemoryError异常。而OutOfMemoryError是指当线程申请栈时发现栈已经满了,而且内存也全都用光了。
3、本地方法栈
a)什么是本地方法栈:
1) 本地方法栈和Java虚拟机栈实现的功能类似,只不过本地方法栈是描述本地方法运行过程的内存模型。
2)本地方法栈也是在方法即将运行被执行的时候,本地方方法栈也会为本地方法创建一个栈帧,用于存放该本地方法在运行过程中需要用到的一些信息。包括:局部变量表、操作数栈、动态链接、方法出口信息等。
3) 本地方法在执行完毕也会将相应 的栈帧出栈并释放内存空间。
4) 本地方法栈也会抛出StackOverFlowError和OutOfMemoryError异常。
4、堆
a) 什么是堆
堆是用来存放对象的内存空间,几乎所有的对象都存储在堆中。
b)堆的特点是什么
1)线程共享:整个虚拟机只有一个堆,所有的线程都访问同一个堆。
2)在虚拟机启动的时候创建堆,在虚拟机关闭的时候销毁堆
3)堆是垃圾回收的主要场所
4) 堆可以进一步分为新生代和老年代,其中新生代有可以进一步分为Eden、From Survior、To Survior.不同的区域存放不同声明周期的对象,这样可以根据不同的区域使用不同的垃圾收集算法,从而是对象回收而更具有针对性,也会变的更加高效。
5) 堆的大小即可以固定也可以动态的扩展,但是主流的虚拟机堆的大小都是可以动态扩展的。
5、方法区
a)什么是方法区
在Java虚拟机规范中定义方法区是堆的一个逻辑部分,方法区中存放已经被虚拟机加载的类信息、常量、静态常量、即时编译器编译后的代码等
b) 方法区的特点
1) 线程共享:方法区是堆的一个逻辑部分,因此和堆一样是线程共享的,整个虚拟机中只有一个堆区域。
2)永久代:方法区中存放的都是需要永久保存的信息,而且它还是堆空间的一个逻辑部分,因此用堆的方法进行划分把方法区分为老年代。
3) 内存回收效率低:方法区中的信息一般需要长期存在,内存回收一遍只有少量的信息是无效的,在方法区中垃圾回收的主要对象是对常量池的回收和对类型的卸载。
4)Java虚拟机规范对方法区的要求比较宽松:和堆一样允许固定大小,也允许动态扩展,还允许不进行垃圾回收。
c) 什么是运行时常量池
一般在一个类中通过public static final来声明一个常量,这个类被编译之后会生成一个Class文件,这个类的全部信息都会包含在这个Class文件中,当这个类被虚拟机加载之后,Class文件中的常量就会被放在方法区的运行时常量池中。在程序运行期间,也可以向常量池中添加常量。如果运行时常量池中的常量长时间没有被对象引用,也没有被变量引用,那么就会被垃圾收集器进行回收。
6、直接内存
直接内存是除了Java虚拟机之外的内存,但也能被Java利用。在NIO中引入了一种基于通道和缓冲的IO方式,它可以通过调用本地方法直接分配Java虚拟机之外的内存,然后通过一个存储在Java堆中的DirectByteBuffer对象直接操作该内存,从而提升了数据操作的效率。
直接内存的大小不受Java虚拟机的控制,但既然是内存,当内存不足的时候也会出现抛出OOM异常。
综上所述:
a)Java虚拟机的内存模型中一共有两个“栈”,分别是:Java虚拟机栈和本地方法栈。两个“栈”的功能类似,都是方法运行过程的内存模型。并且两个“栈”内部构造相同,都是线程私有。只不过Java虚拟机栈描述的是Java方法运行过程的内存模型,而本地方法栈是描述Java本地方法运行过程的内存模型。
b)Java虚拟机的内存模型中一共有两个“堆”,一个是原本的堆,一个是方法区。方法区本质上是属于堆的一个逻辑部分。堆中存放对象,方法区中存放类信息、常量、静态变量、即时编译器编译的代码。
c)堆是Java虚拟机中最大的一块内存区域,也是垃圾收集器主要的工作区域。
d) 程序计数器、Java虚拟机栈、本地方法栈是线程私有的,即每个线程都拥有各自的程序计数器、Java虚拟机栈、本地方法区。并且他们的生命周期和所属的线程一样。
e)而堆、方法区是线程共享的,在Java虚拟机中只有一个堆、一个方法栈。并在JVM启动的时候就创建,JVM停止才销毁。
深入理解JVM(1)——JVM内存模型的更多相关文章
- (转载)JVM中的内存模型与垃圾回收
转载自微信公众号:Java高级架构(Java-jiagou)-----看完这篇文章,我奶奶都知道JVM中的内存模型与垃圾回收了! 六.内存模型 6.1 内存模型与运行时数据区 Java虚拟机在执行J ...
- JVM学习笔记——内存模型篇
JVM学习笔记--内存模型篇 在本系列内容中我们会对JVM做一个系统的学习,本片将会介绍JVM的内存模型部分 我们会分为以下几部分进行介绍: 内存模型 乐观锁与悲观锁 synchronized优化 内 ...
- 深入理解JVM(6)——Java内存模型和线程
Java虚拟机规范中定义了Java内存模型(Java Memory Model,JMM)用来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果(“即Ja ...
- 深入理解JAVA虚拟机(内存模型+GC算法+JVM调优)
目录 1.Java虚拟机内存模型 1.1 程序计数器 1.2 Java虚拟机栈 局部变量 1.3 本地方法栈 1.4 Java堆 1.5 方法区(永久区.元空间) 附图 2.JVM内存分配参数 2.1 ...
- 理解JVM之java内存模型
java虚拟机规范中试图定义一种java内存模型(JMM)来屏蔽掉各种硬件和操作系统内存访问差异,以实现让java程序在各种平台都能打到一致的内存访问效果.所以java内存模型的主要目标是定义程序中各 ...
- 【JVM】JVM系列之内存模型(六)
一.前言 经过前面的学习,我们终于进入了虚拟机最后一部分的学习,内存模型.理解内存模型对我们理解虚拟机.正确使用多线程编程提供很大帮助.下面开始正式学习. 二.Java并发基础 在并发编程中存在两个关 ...
- JVM学习--(二)内存模型、可见性、指令重排序
我们将根据JVM的内存模型探索java当中变量的可见性以及不同的java指令在并发时可能发生的指令重排序的情况. 内存模型 首先我们思考一下一个java线程要向另外一个线程进行通信,应该怎么做,我们再 ...
- 【JVM】Java内存模型
原文:多线程之Java内存模型(JMM)(一) 概述 多任务和高并发是衡量一台计算机处理器的能力重要指标之一.一般衡量一个服务器性能的高低好坏,使用每秒事务处理数(Transactions Per S ...
- jvm(12)-java内存模型与线程
[0]README 0.1)本文部分文字描述转自“深入理解jvm”,旨在学习“java内存模型与线程” 的基础知识: [1]概述 1)并发处理的广泛应用是使得 Amdahl 定律代替摩尔定律称为计 ...
- 看完这篇文章,我奶奶都知道什么是JVM中的内存模型与垃圾回收!
扩展阅读:JVM从入门开始深入每一个底层细节 六.内存模型 6.1.内存模型与运行时数据区 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干不同数据区域. Java内存模型的主要目 ...
随机推荐
- 下载离线VS2017
1.下载工具 版本 文件 Visual Studio Enterprise (企业版) vs_enterprise.exe Visual Studio Professional (专业版) vs_pr ...
- Beyond-Compare 4 -linux 破解
key失效了可以去https://www.serials.be/serial/Beyond_Compare_4_Linux_68803632.html生成 Crack-Beyond-Compare-l ...
- Go语言之闭包
闭包的最初目的是为了减少全局变量,在函数调用过程中,隐式的传递共享变量. 但这样的编辑,带来的坏处是不够直接清晰. 所以,如非必要,不要使用. 对象是附有行为的数据,它在类中集中定义, 而闭包是附有数 ...
- linux服务器性能——CPU、内存、流量、磁盘使用率的监控
https://blog.csdn.net/u012859748/article/details/72731080
- jquery轻量级数字动画插件jquery.countup.js
插件描述: jquery.countup.js 是一款轻量级jquery数字动画插件.该数字动画插件可以在页面滚动时,将指定的数字从0开始计数增加动画. 插件说明 jquery.countup.js ...
- Delphi Setlength 内存释放总结
https://blog.csdn.net/lotusyangjun/article/details/8203521 一.在Setlength 被调用次数不多时,可直接使用以下代码进行释放var aa ...
- python sqlite3查看数据库所有表(table)
#coding:utf-8 import sqlite3 ''' sqlite3存在系统表sqlite_master,结构如下: sqlite_master( type TEXT, #类型: ...
- [转]Maven与nexus关系
开始在使用Maven时,总是会听到nexus这个词,一会儿maven,一会儿nexus,当时很是困惑,nexus是什么呢,为什么它总是和maven一起被提到呢? 我们一步一步来了解吧. 一.了解Mav ...
- jQuery插件学习之选项卡Tab
在网站开发中经常会用到选项卡功能,为了节省一下写代码时间,封装了一下tab插件,方便调用. 来看一下效果: tab-1 tab-2 tab-3 tabs-1-panel tabs-2-panel ta ...
- WebApi 得到提交过来的 post 数据
byte[] byts = new byte[System.Web.HttpContext.Current.Request.InputStream.Length]; System.Web.HttpCo ...