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虚拟机的内存的更多相关文章

  1. 如何写出让java虚拟机发生内存溢出异常OutOfMemoryError的代码

    程序小白在写代码的过程中,经常会不经意间写出发生内存溢出异常的代码.很多时候这类异常如何产生的都傻傻弄不清楚,如果能故意写出让jvm发生内存溢出的代码,有时候看来也并非一件容易的事.最近通过学习< ...

  2. 深入理解java虚拟机【内存溢出实例】

    通过简单的小例子程序,演示java虚拟机各部分内存溢出情况: (1).java堆溢出: Java堆用于存储实例对象,只要不断创建对象,并且保证GC Roots到对象之间有引用的可达,避免垃圾收集器回收 ...

  3. 从Java虚拟机的内存区域、垃圾收集器及内存分配原则谈Java的内存回收机制

    一.引言: 在Java中我们只需要轻轻地new一下,就可以为实例化一个类,并分配对应的内存空间,而后似乎我们也可以不用去管它,Java自带垃圾回收器,到了对象死亡的时候垃圾回收器就会将死亡对象的内存回 ...

  4. Java虚拟机:内存模型详解

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 我们都知道,当虚拟机执行Java代码的时候,首先要把字节码文件加载到内存,那么这些类的信息都存放在内存中的哪个区域呢?当我们创建一个对象实 ...

  5. 初识:java虚拟机的内存划分

    什么是内存? 内存是计算机中的重要原件,临时存储区域,作用是运行程序.我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的,必须放进内存中才能运行,运行完毕后会清空内存.Java虚拟机要运行程序 ...

  6. java虚拟机的内存模型

    一.为什么要了解java虚拟机的内存模型 java虚拟机作为java代码运行的平台,是java技术的基石.了解java虚拟机的内存模型也就变得十分必要.它能帮助我们更好的了解java代码的运行机制,更 ...

  7. java虚拟机的内存机制

    我们都知道,java程序的跨平台性离不开java虚拟机,虚拟机隔绝了底层操作系统,使得java程序可以直接运行在虚拟机之上.所以,对java的学习,离不开对java虚拟机的学习与了解.下面简单整理下j ...

  8. Java虚拟机的内存管理

    众所周知,Java程序员写的代码是没有办法控制Java对象的内存释放的,完全有JVM暗箱操作. 虽然程序员把内存的释放的任务都交给了Java虚拟机,但是并不代表Java程序就不存在内存泄漏. 反而,某 ...

  9. 1 - JVM随笔分类(java虚拟机的内存区域分配(一个不断记录和推翻以及再记录的一个过程))

    java虚拟机的内存区域分配   在JVM运行时,类加载器ClassLoader在加载到类的字节码后,交由jvm的执行引擎处理, 执行过程中需要空间来存储数据(类似于Cpu及主存),此时的这段空间的分 ...

  10. JAVA虚拟机:内存各个区介绍

    概述:java应用程序由java虚拟机自动管理程序执行期间内存管理. 优势:1.不再需要程序员去为使用的内存在程序中手动编写释放内存代码. 2.由虚拟机管理内存不容易出现内存泄漏和内存溢出的问题. 缺 ...

随机推荐

  1. Netty源码分析之ChannelPipeline(一)—ChannelPipeline的构造与初始化

    Netty中ChannelPipeline实际上类似与一条数据管道,负责传递Channel中读取的消息,它本质上是基于责任链模式的设计与实现,无论是IO事件的拦截器,还是用户自定义的ChannelHa ...

  2. F#周报2019年第43期

    新闻 F# eXchange 2020--征文通知 FSSF在忙什么?2019年第三季度版本 Miguel强烈推荐使用TensorFlow.NET 运行在ASP.NET Core 3上的SAFE-Bo ...

  3. dom 创建时间

    下面讲述如何在页面生成一个装有日期的盒子 首先写出一个日期的函数进行赋值使用document.createElement创建一个文档节点div,然后将时间函数输出在div之中,利用document.b ...

  4. python【控制台】小游戏--贪吃蛇

    传统贪吃蛇相信大家都玩过,也是一款很老很经典的游戏,今天我们用python控制台实现 项目有很多bug没有解决,因为本人一时兴起写的一个小游戏,所以只是实现可玩部分功能,并没有花较多的时间和精力去维护 ...

  5. GPU服务器及计算原理

    图形处理器(英语:Graphics Processing Unit,缩写:GPU),又称显示核心.视觉处理器.显示芯片,是一种专门在个人电脑.工作站.游戏机和一些移动设备(如平板电脑.智能手机等)上图 ...

  6. CentOS生产环境无网络安装percona-xtrabackup2.4【RPM安装教程】

    Percona XtraBackup 8.0不支持对在MySQL 8.0之前的版本,Percona Server for MySQL或 Percona XtraDB Cluster中创建的数据库进行备 ...

  7. 几种部署Goku API Gateway的方式,最快一分钟可使用上网关

    本文将介绍几种部署Goku API Gateway的方式,最快一分钟可使用上为网关,详情请看全文. 什么是Goku API Gateway? Goku API Gateway (中文名:悟空 API ...

  8. 星级评分条(RatingBar)的功能与用法

    星级评分条与拖动条有相同的父类:AbsSeekBar,因此它们十分相似.实际上星际评分条与拖动条的用法.功能都十分接近:它们都允许用户通过拖动来改变进度.RatingBar与SeekBar的最大区别在 ...

  9. regexp盲注的一些改进

    index.php?id=1 and 1=(SELECT 1 FROM information_schema.tables WHERE TABLE_SCHEMA="blind_sqli&qu ...

  10. RocketMQ 消息发送system busy、broker busy原因分析与解决方案

    目录 1.现象 2.原理解读 2.1 RocketMQ 网络处理机制概述 2.2 pair.getObject1().rejectRequest() 2.3 漫谈transientStorePoolE ...