1、运行时数据区域

  Java虚拟机会将内存区域划分为几个区域,每个区域储存不同类型的数据或承担不同的功能。

  PC,堆-Java堆,栈-虚拟机栈、本地方法栈,方法区、直接内存

  当类被实例化或static方法被调用时,Class文件被加载,关于类的信息储存在方法区里(有了模子)。虚拟机获得了类的相关信息,就可以在Java堆里创建实例对象了。类方法被调用时,便会在Java栈中产生一个栈帧来记录调用的上下文信息,其中局部变量表中保存了指向Java堆中实例对象的引用以便操纵对象。当程序的执行需要调用由其他语言编写的方法时(系统调用等的dll),就需要本地方法栈来服务。

  1.1、程序计数器PC

    下一条指令(字节码)的地址,通过改变PC的值来完成程序状态切换。多线程中,每个线程都有自己的执行流程,因此它们要有自己的程序计数器PC

    执行Native方法时,PC为空(Undefined)。

    没有OutOfMemoryError。

  1.2、Java虚拟机栈

    描述Java方法的执行,线程私有,生命周期与线程相同。每个方法被调用时,都会在虚拟机栈中创建一个栈帧(Stack Frame),其中记录了方法执行的上下文信息(局部变量表、操作数栈、动态链    接、方法返回等)。通常所说的堆内存、栈内存一般指Java堆虚拟机栈(局部变量表部分)

    局部变量表存放编译时确定的各种基本数据类型(boolea...、reference、returnAddress),局部变量表所需空间在编译时完成分配,运行期间不会改变。

    栈深度超过最大值时-StackOverflowError;扩展时无法申请到足够内存-OutOfMemoryError。

  1.3、本地方法栈

    虚拟机栈为虚拟机运行Java方法(Java字节码)服务,而本地方法栈为虚拟机使用到的Native方法本地方法)服务。

    什么是本地方法?——"A native method is a Java method whose implementation is provided by non-java code."

    Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C。

    StackOverflowError,OutOfMemoryError。

  1.4、Java堆

    存放类的实例对象,由所有线程共享。所有的对象实例以及数组都要在堆上分配(数组也是一种对象,不同类型数组会有不同的类)。

    Java堆也是GC的主要管理区域,从垃圾回收角度看,Java堆可以细分为Young Generation(新生代)Old Generation(老年代)

    更加细分可以分为Eden空间From Survivor空间To Survivor空间等。划分的目的只是为了更好的进行垃圾回收。

    逻辑地址连续,物理地址可不连续。

    堆无法扩展时抛出OutOfMemoryError

    关于新生代、老年代、永久代更详细的介绍可参见:https://www.jianshu.com/p/d3a0b4e36c28

  1.5、方法区

    储存被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,由所有线程共享。

    常量池:Class文件一部分,存放编译期生成的各种字面量和符号引用。在类加载后存放入运行时常量池。

    运行时常量池:方法区的一部分,相较于常量池更动态,运行期间也可能有新的常量放入。

  1.6、直接内存

    Direct Memory,不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域。

    NIO中使用的基于Channel和Buffer的IO方式可使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象操纵。避免了在Java堆和Native堆中来回复制,提高了性能。

  1.7、HotSpot对象创建过程

    1、new

    2、在常量池中寻找符号引用

    3、检查符号代表的类是否被加载、解析和初始化过,没有加载则进行加载,找不到Class文件则报ClassNotFind错误

    4、为新生对象分配内存:

      紧缩过的内存采用Bump the Point方式,即指针向空闲区域移动对象大小长度

      内存没有紧缩过,不规整,则采用Free List方式,在记录的空闲块中寻找相应大小的块来分配

      保证内存分配时的线程安全性:

        1、采用同步处理,Compare And Set 加失败重试。

        2、为每个线程预分配单独的空间,线程在其自己的空间上创建对象,但是,线程空间扩容时还是要进行同步处理。

    5、将分配出的空间初始化为0(不包括对象头)

    6、对对象头中信息进行必要设置

    7、执行<init>进行对象初始化

  1.8、对象内存布局

    Header(对象头)、(Instance Data)实例数据、Padding(对其填充)

    Header分为两部分,第一部分存储对象的自身的运行时数据(HashCode、GC分代年龄、锁状态标记等);第二部分是类型指针,指向方法区中类的元数据信息。如果对象是一个数组,则还要有长度信息。

    Instance Data部分存储对象的实例信息,包括它自己的以及继承而来的所有信息。存储顺序受虚拟机分配策略参数和字段在源码中定义顺序影响。

    Padding只起占位符作用,受JVM对对象起始地址的要求影响。

  1.9、对象访问定位

    对象是在堆上创建的,而操作对象需要通过Java栈上的reference数据来进行。

    主流方式有句柄直接指针两种。

    句柄池中的句柄保存了对象实例数据地址以及对象的类型数据(元数据)地址,reference中存储对象句柄的地址即可定位到对象和其元数据。

    采用直接指针时,reference指向对象地址,对象的对象头中的类型指针指向其元数据地址

    句柄的优势是稳定,对象位置移动时,只需改动句柄中的数据,而reference本身不用改变。

    直接指针直接指向对象,因此访问速度快

  1.10、内存区域相关的JVM参数

    Xms20m 堆的最小值设为20m

    Xmx20m 堆的最大值设为20m

    XX:+HeapDumpOnOutOfMemoryError 让虚拟机在出现内存溢出时Dump出当前内存堆转储快照以便时候分析

    Xss128k 设定栈容量为128k

    Xoss128k 设置本地方法栈大小为128k(HotSpot不区分虚拟机栈和本地方法栈,因此该方法无用)

    XX:MaxPermSize 设置方法区最大值

    XX:PermSize 设置方法区大小

    XX:MaxDirectMemorySize 设置最大直接内存大小,如不指定则与Java最大值一样

    

    

深入理解jvm-2Edition-Java内存区域的更多相关文章

  1. 理解JVM之Java内存区域

    Java虚拟机运行时数据区分为以下几个部分: 方法区.虚拟机栈.本地方法栈.堆.程序计数器.如下图所示: 一.程序计数器 程序计数器可看作当前线程所执行的字节码行号指示器,字节码解释器工作时就是通过改 ...

  2. 深入理解JVM - 1 - Java内存区域划分

    作者:梦工厂链接:https://www.jianshu.com/p/7ebbe102c1ae来源:简书简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处. Java与C++之间有一堵 ...

  3. 深入理解JVM(一)--Java 内存区域

    一.  运行时数据区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域. Java虚拟机所管理的内存将会包括以下几个运行时数据区域:               ...

  4. 深入理解JVM(二)Java内存区域

    2.1 C.C++内存管理是由开发人员管理,而Java则交给了JVM进行自动管理 2.2 JVM运行时数据区:方法区.堆(运行时线程共享),虚拟机栈.本地方法栈.程序计数器(运行时线程隔离,私有) 1 ...

  5. JVM之Java内存区域

    JVM之Java内存区域 世界上并没有完美的程序,但我们并不因此而沮丧,因为写程序本来就是一个不断追求完美的过程. 一.JAVA内存区域 谈及JAVA虚拟机运行时数据区域就不得不祭出这张经典的图了: ...

  6. 学习jvm(一)--java内存区域

    前言 通过学习深入理解java虚拟机的教程,以及自己在网上的查询的资料,做一个对jvm学习过程中的小总结. 本文章内容首先讲解java的内存分布区域,之后讲内存的分配原则以及内存的监控工具.再下来会着 ...

  7. 深入理解JVM(6)——Java内存模型和线程

    Java虚拟机规范中定义了Java内存模型(Java Memory Model,JMM)用来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果(“即Ja ...

  8. 史上最详细JVM,Java内存区域讲解

    本人免费整理了Java高级资料,一共30G,需要自己领取:传送门:https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q 运行时数据区域 JVM载执行Jav ...

  9. JVM:Java内存区域与内存溢出异常

    Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁时间,有些区域随着虚拟机进程的启动而存在,有些区域依赖用户线程的启动和 ...

  10. 深入理解虚拟机之Java内存区域

    1 概述 对于Java程序员来说,在虚拟机自动内存管理机制下,不再需要像C/C++程序开发程序员这样为内一个new 操作去写对应的delete/free操作,不容易出现内存泄漏和内存溢出问题.正是因为 ...

随机推荐

  1. cache之guava

    本文主要记录guava_cache的学习心得! 缓存是什么?为何要用缓存呢? 先参考下图! 这是一张小白图!简单形容了一个普普通通的服务端请求的处理模型! 当一个request请求通过网络不远千里的来 ...

  2. Jenkins 进阶篇 - 权限配置

    Jenkins的授权策略 Jenkins 默认的授权策略是[登录用户可以做任何事],也就是人人都是管理员,可以修改所有的设置以及构建所有的任务,不用做任何设置,有账号登录到 Jenkins 系统即可, ...

  3. 免费版:Xshell和Xftp下载路径

    家庭版Xshell和Xftp下载地址: 下载地址:https://www.netsarang.com/zh/free-for-home-school/

  4. Spring:Spring-IOC三种注入方式、注入不同数据类型

    一.Spring IOC(依赖注入的三种方式): 1.Setter方法注入 package com.jpeony.spring.setter; import com.jpeony.spring.com ...

  5. mysql 深度解析auto-increment自增列"Duliplicate key"问题

    转载自:https://cloud.tencent.com/developer/article/1367681 问题描述 近期,线上有个重要Mysql客户的表在从5.6升级到5.7后master上插入 ...

  6. hdu 1145(Sticks) DFS剪枝

    Sticks Problem Description George took sticks of the same length and cut them randomly until all par ...

  7. 元素类型为 "configuration" 的内容必须匹配 "(properties?,settings?,typeAliases?,typeHandlers?

    报错主要部分如下: Error building SqlSession.### Cause: org.apache.ibatis.builder.BuilderException: Error cre ...

  8. ios多线程开发基础

    多线程编程:下载数据时,开辟子线程,减少阻塞时间,和主线程并发运行,提升用户体验 1.Thread 1>新建Thread对象,带一selector方法,调用start方法,开启子线程 2> ...

  9. java基础---枚举类与注解

    一.枚举类 类的对象只有有限个,确定的.我们称此类为枚举类 如果枚举类中只有一个对象,则可以作为单例模式的实现方式. 定义枚举类 方式一:jdk5.0之前,自定义枚举类 public class Se ...

  10. FreeRTOS-00-基础知识+任务创建删除

    1 说明 本文仅作为学习FreeRTOS的记录文档,作为初学者肯定很多理解不对甚至错误的地方,望网友指正. 1.1 简介 FreeRTOS是一个RTOS(实时操作系统)系统,支持抢占式.合作式和时间片 ...