Java虚拟机的内存
JDK1.8之前,java内存分为 线程共享区:堆、方法区、直接内存(非运行时数据区的一部分)。线程私有区:程序计数器、虚拟机栈、本地方法栈。
JDK1.8开始,虚拟机取消了方法区,改为元空间。
程序计数器:
程序计数器是一块小的内存空间,存放线程执行的信息,如字节码的行号指示器还有分支、循环、跳转、异常处理等都需要依赖计数器来完成。就是记录程序运行到哪个位置了,这样方便线程切换后能恢复到正确的执行位置,每个线程都需要有一个独立的程序计数器,所以它是线程私有的。它的生命周期随着线程的创建而创建,随着线程的结束而死亡。并且是唯一一个不会出现OutOfMemoryError的内存区域。
Java虚拟机栈:
它的生命周期也和线程相同,是线程私有的,描述的是java方法执行的内存模型,每次方法调用的数据都是通过栈传递的。Java虚拟机栈是由一个个栈帧组成,每个栈帧中都拥有:局部变量表、操作数栈、动态链接、方法出口信息。
局部变量表主要存放了编译器可知的各种数据类型(八大基本数据类型)和对象引用。
它会出现两种异常:StackOverFlowError和OutOfMemoryError。
StackOverFlowError:虚拟机栈的内存不允许动态扩展,当线程请求栈的深度超出当前栈深度,就会抛出该异常。
OutOfMemoryError:虚拟机栈的内存大小允许动态扩展,且当线程请求时内存用完了,无法再动态扩展了就会抛出该异常。
每一次函数调用都会有一个对应的栈帧被压入栈,调用结束后,栈帧就会被弹出。无论是return还是抛出异常都会导致栈帧弹出。
本地方法栈:
听名字就知道,这是一个执行本地方法(Native方法)时候使用的栈。虚拟机栈是执行java方法的时候使用的栈。其它工作原理跟java虚拟机栈一样,只是服务的对象不一样而已,这里就不做介绍了。
堆(Heap):
作为虚拟机内存中最大的一块区域,这是一块共享的内存区域,在虚拟机启动的时候创建。这个区域存放对象的实例,几乎所有的对象实例以及数组都在这里分配内存。这一块也是垃圾收集器主要管理的区域,现在收集器基本都采用分代收集算法,内存区域也可以大致划分为新生代和老年代。对象从新生代到老年代的年龄阈值可以通过参数设置。
方法区:
与堆一样也是线程共享的内存区域,它用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。这个区域常被称作“永久代”,但实际上,垃圾收集行为在这个区域只是比较少出现,但并非数据进入方法去后就永久存在了。
运行时常量池:
它是方法区的一部分,(用于存放编译期生成的各种字面量和符号引用)
JDK1.7之后的版本的JVM已经将运行时常量池从方法区中移了出来,在java堆中开辟了一块内存区域用来存放运行时常量池。
直接内存:
直接内存并不是虚拟机运行时数据区的一部分,也不是虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使用。而且也可能导致OutOfMemoryError异常的出现。
对象的创建过程:
第一步:类加载检查
虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载过、解析和初始化过。如果没有,那必须先执行相应的类加载过程。
第二步:分配内存
在类加载检查通过后,接下来虚拟机将为新生对象分配内存。对象所需的内存大小在类加载检查完成后便可确定,为对象分配空间的任务等同于把一块确定大小的内存从java堆中划分出来。分配方式有指针碰撞和空闲列表两种方式,指针碰撞需要内存规整,即没有内存碎片的时候使用该方法;空闲列表则是在有内存碎片的情况下使用。
第三步:初始化零值
内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头),这一不操作保证了对象的实例字段在java代码中可以不赋初值就直接使用,程序能访问到这些字段的数据类型所对应的零值。
第四步:设置对象头
初始化零值完成之后,虚拟机要对对象头进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。这些信息存放在对象头中。
第五步:执行init方法
在上面工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了,但从java程序员的视角来说,对象创建才刚刚开始,init方法还没有执行,所有的字段都是为零。所以一般来说,执行new指令之后会接着执行init方法,把对象按照程序员的意愿进行初始化,这样一个真正的可用的对象才算完全生产出来。
对象的访问定位:
句柄:使用句柄的方式的话,java堆中会划分一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。访问对象时需要两次定位操作,先定位到句柄,再通过句柄的地址信息定位到对象。但是当对象被移动时只会改变句柄中的实例数据指针,reference不需要修改。
直接指针:reference存放的直接就是对象的地址。只需要一次指针定位,速度快。
Java虚拟机的内存的更多相关文章
- 如何写出让java虚拟机发生内存溢出异常OutOfMemoryError的代码
程序小白在写代码的过程中,经常会不经意间写出发生内存溢出异常的代码.很多时候这类异常如何产生的都傻傻弄不清楚,如果能故意写出让jvm发生内存溢出的代码,有时候看来也并非一件容易的事.最近通过学习< ...
- 深入理解java虚拟机【内存溢出实例】
通过简单的小例子程序,演示java虚拟机各部分内存溢出情况: (1).java堆溢出: Java堆用于存储实例对象,只要不断创建对象,并且保证GC Roots到对象之间有引用的可达,避免垃圾收集器回收 ...
- 从Java虚拟机的内存区域、垃圾收集器及内存分配原则谈Java的内存回收机制
一.引言: 在Java中我们只需要轻轻地new一下,就可以为实例化一个类,并分配对应的内存空间,而后似乎我们也可以不用去管它,Java自带垃圾回收器,到了对象死亡的时候垃圾回收器就会将死亡对象的内存回 ...
- Java虚拟机:内存模型详解
版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 我们都知道,当虚拟机执行Java代码的时候,首先要把字节码文件加载到内存,那么这些类的信息都存放在内存中的哪个区域呢?当我们创建一个对象实 ...
- 初识:java虚拟机的内存划分
什么是内存? 内存是计算机中的重要原件,临时存储区域,作用是运行程序.我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的,必须放进内存中才能运行,运行完毕后会清空内存.Java虚拟机要运行程序 ...
- java虚拟机的内存模型
一.为什么要了解java虚拟机的内存模型 java虚拟机作为java代码运行的平台,是java技术的基石.了解java虚拟机的内存模型也就变得十分必要.它能帮助我们更好的了解java代码的运行机制,更 ...
- java虚拟机的内存机制
我们都知道,java程序的跨平台性离不开java虚拟机,虚拟机隔绝了底层操作系统,使得java程序可以直接运行在虚拟机之上.所以,对java的学习,离不开对java虚拟机的学习与了解.下面简单整理下j ...
- Java虚拟机的内存管理
众所周知,Java程序员写的代码是没有办法控制Java对象的内存释放的,完全有JVM暗箱操作. 虽然程序员把内存的释放的任务都交给了Java虚拟机,但是并不代表Java程序就不存在内存泄漏. 反而,某 ...
- 1 - JVM随笔分类(java虚拟机的内存区域分配(一个不断记录和推翻以及再记录的一个过程))
java虚拟机的内存区域分配 在JVM运行时,类加载器ClassLoader在加载到类的字节码后,交由jvm的执行引擎处理, 执行过程中需要空间来存储数据(类似于Cpu及主存),此时的这段空间的分 ...
- JAVA虚拟机:内存各个区介绍
概述:java应用程序由java虚拟机自动管理程序执行期间内存管理. 优势:1.不再需要程序员去为使用的内存在程序中手动编写释放内存代码. 2.由虚拟机管理内存不容易出现内存泄漏和内存溢出的问题. 缺 ...
随机推荐
- 玩转ArduinoJson库 V6版本
1.前言 前面,博主已经讲解了ArduinoJson库的V5版本.为了节省时间以及不讨论重复内容,博主建议读者先去阅读一下 玩转ArduinoJson库 V5版本 .重点了解几个东西: JSO ...
- JavaScript Array返回值以及是否改变原数组。
1. push:最后一位新增://改变原数组 arr.push("123"); 返回值是数组的长度: var b = ...
- fenby C语言 P18
#include <stdio.h> int main(){ int i; for(i=1;i<=15;i++) { if((i%2==1)) { printf("%d\n ...
- incompatible implicit declaration of built-in function 'fabs'
形如: float a = -3.0; float b = fabs(a); 形参数据类型和实参数据类型完全一致,却还报警告: incompatible implicit declaration of ...
- 2018.8.1 python中字典的增删改查及其它操作
一.字典的简单介绍 1.dict 用{}来表示 键值对数据 {key:value} 唯一性 2.键都必须是可哈希,不可变的数据类型就可以当做字典中的键 值没有任何限制 ...
- javadoc的使用
在进行项目开发过程中,项目接口文档是很重要的一块内容,在java项目中我们可以用swagger,asciidoc,javadoc等方式来生产文档,而其中最基本的文档生成方式就是javadoc,它一般用 ...
- CMMS系统中的物联监测
有条件的设备物联后,可时实查看设备运行状态,如发现异常,可提前干预.
- 全栈项目|小书架|服务器开发-Koa2 全局异常处理
什么是异常 做开发的基本都知道异常,像Android开发中常见的ANR异常.空指针异常,服务器开发中经常遇到的异常404,500异常,还有一些其他常见的异常,具体可见HTTP状态码. 基本上这些异常可 ...
- Redis实战--Redis整合SpringBoot示例
echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!!! 该文章 ...
- 从BIO到Netty的演变
从BIO到Netty的演变 前言 计算机网络可以说是每个学计算机的都绕不过去的一道坎.计算机网络到底有多么重要,你走到大学图书馆的计算机部分,翻开那些什么<从零开始:黑客XXX>,< ...