一 Java内存区域与HotSpot虚拟机对象
1 Java技术体系、JDK、JRE?
    Java技术体系包括:
        · Java程序设计语言;
        · 各种硬件平台上的Java虚拟机;
        · Class文件格式;
        · Java API类库;
        · 来自商业机构或开源社区的第三方Java类库。
    JDK,即Java开发工具包,包括Java程序设计语言、Java虚拟机、Java API类库,是用于支持Java程序开发的最小环境;不仅提供了Java程序运行所需要的JRE,还提供了一系列的编译、调试工具,如javac、jconsole等。
    JRE,即Java运行时环境,包括Java API类库中的Java SE API子集和Java虚拟机两部分,是用于支持Java程序运行的标准环境。
 
2 Java内存区域如何划分?
    Java内存区域分为五部分:程序计数器、虚拟机栈、本地方法栈、方法区、堆。
    (1)程序计数器:
    ---当前线程所执行的字节码的行号指示。若线程正在执行的是一个java方法,则计数器记录的是正在执行的虚拟机字节码指令;若线程正在执行的是一个Native方法(本地方法),则计数器值为空;
    ---线程私有的;
    ---唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
    (2)虚拟机栈:
    ---描述的是Java方法执行的内存模型:每个方法在执行时都会创建一个栈帧用于存储局部变量、操作数栈、动态链接、方法出口等信息;每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
    ---线程私有的,生命周期与线程相同;
    ---使用连续的内存空间;
    ---两种异常:若线程请求的栈深度大于虚拟机所允许的深度,抛出StackOverflowError异常;若虚拟机栈可以动态扩展,当扩展时无法申请到足够的内存,抛出OutOfMemoryError异常。
    (3)本地方法栈:
    ---本地方法栈和虚拟机栈的唯一区别是虚拟机栈是为虚拟机执行java方法服务,而本地方法栈为虚拟机执行Native方法服务,其他与虚拟机栈一样。
    (4)Java堆:
    ---虚拟机启动时创建,用于存放对象实例,几乎所有的对象实例都在Java堆中分配内存(随着JIT编译器的发展和逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术可能导致对使得实例在栈上直接分配);
    ---所有线程共享的;
    ---是垃圾收集器管理的主要区域。从内存回收角度,可分为:新生代和老年代;从内存分配的角度,Java堆中可分出多个线程私有的分配缓冲区(TLAB)。
    ---可以处于物理上不连续的内存空间、可以选择固定大小或者可扩展。可能抛出OutOfMemoryError异常。
    (5)方法区:(HotSpot: 永久代)
    ---用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据;
    ---线程共享的;
    ---此区域内存回收的主要目标是常量池的回收和类型的卸载;
         ---不需要连续内存、可以选择固定大小或者可扩展、还可以选择不进行垃圾收集。当无法满足内存分配需求时,将抛出OutOfMemoryError异常。
 
3 运行时常量池
        ---运行时常量池是方法区的一部分;
        ---Class文件中的常量池用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放;
        ---Java虚拟机规范没有对运行时常量池做任何细节的要求,不同的提供商实现的虚拟机可以按照自己的需要来实现这个内存区域;
        ---具备动态性,运行期间也可能将新的常量放入池中,如String类的intern()方法。
 
4 对象的创建过程
    普通Java对象(不包括数组和Class对象)的创建过程为:
        (1)首先检查new指令的参数能否在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载、解析和初始化过,如果没有,则先执行相应的类加载过程。
        (2)在类加载检查通过后,虚拟机将为新生对象分配内存。
                分配方式有:
                    · “指针碰撞”:当Java堆中内存是绝对规整的,所有用过的内存放在一边,空闲的内存放在另一边,中间放着一个指针作为分界点的指示器。此时,分配内存仅需要把那个指针向空闲空间那边挪动一段与对象大小相等的距离。
                    · “空闲列表”:当Java堆中的内存不是规整的,此时,虚拟机必须维护一个列表,记录上哪些内存块是可用的,分配的时候从列表中找到一块足够大的空间划分给对象实例,并且更新列表上的记录。
              选择哪种分配方式是由Java堆是否规整决定,而Java堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定。因此,使用Serial、ParNew等带Compact过程的收集器时,系统采用的分配方式为指针碰撞;使用CMS这种基于标记-清除算法的收集器,系统采用的分配方式为空闲列表。
                分配内存的操作在并发情况下并不是线程安全的,解决方法有:
                    · 对分配内存空间的动作进行同步处理,而实际上虚拟机采用CAS配上失败重试的方式保证更新操作的原子性。
                    · 把内存分配的动作按照线程划分在不同的空间中进行,即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲(TLAB)。
        (3)虚拟机将分配到的内存空间都初始化为零值(不包括对象头)。
        (4)虚拟机对对象进行必要的设置,如这个对象是哪个类的实例、对象的哈希码、对象的GC分代年龄等。
        (5)一般来说,执行new指令之后还会接着执行<init>方法,把对象按照程序员的意愿进行初始化。
5 对象的内存布局
    对象在内存中存储的布局可分为3块区域:对象头、实例数据、对齐填充。
    对象头包括两部分:
        · 存储对象自身的运行时数据(Mark Word),如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。考虑到虚拟机的空间效率,Mark Word被设计成根据对象的状态复用自己的存储空间。
        · 类型指针,即对象指向它的类元数据的指针。若对象是一个Java数组,则还必须有一块用于记录数组长度的数据。
    实例数据:在程序代码中所定义的各种类型的字段内容,包括父类继承下来的和子类中所定义的。存储顺序受虚拟机分配策略参数和字段在Java源码中定义顺序的影响。规则:相同宽度的字段总是被分配到一起,在父类中定义的变量会出现在子类之前。
    对齐填充:起占位符的作用。对象的大小必须是8字节的整数倍。
6 对象的访问方式
    (1)使用句柄访问
            方式:Java堆中划分出一块内存作为句柄池,reference中存储的是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息。
            优点:reference中存储的是稳定的句柄地址,对象被移动时只会改变句柄中的实例数据指针,reference本身不需要修改。

    (2)使用直接指针访问
            方式:reference中存储的是对象地址。
            优点:节省了一次指针定位的时间开销,速度更快。

 

深入理解Java虚拟机读书笔记1----Java内存区域与HotSpot虚拟机对象的更多相关文章

  1. 《Effective Java》读书笔记(一)之创建和销毁对象

    最近在研读<Effective Java>一书,读书不做点笔记,感觉很容易就忘掉,于是用本篇博客来记录阅读此书的笔记. 郑重声明: 由于是<Effective Java>一书的 ...

  2. 深入理解Java虚拟机 -- 读书笔记(1):JVM运行时数据区域

    深入理解Java虚拟机 -- 读书笔记:JVM运行时数据区域 本文转载:http://blog.csdn.net/jubincn/article/details/8607790 本系列为<深入理 ...

  3. 《深入理解 Java 虚拟机》读书笔记:Java 内存区域与内存溢出异常

    前言 最近开始看这本书,记得前段时间拿起这本书的时候,心情是相当沉重的!当时的剧本是这样的-- 内景.家里 - 下午 我(画外):唉,有点无聊啊!(偶然撇过书架)这么多书得看到什么时候啊,要不要拿一本 ...

  4. 深入理解Java虚拟机之读书笔记一 自动内存管理机制

    一.运行时数据区域 1.程序计数器是线程的私有空间,每个线程都有.针对线程执行的是Java代码还是Native代码有两种取值,Java代码时:虚拟机字节码指令的地址:Native代码时:计数值为Und ...

  5. 深入理解Java虚拟机——读书笔记

    首先 强烈推荐周志明老师的这本书,真的可以说是(起码中文出版界)新手了解Java虚拟机必须人手一本的教科书!!!   第二部分自动内存管理机制 由于Java虚拟机的多线程是通过线程轮流切换并分配处理器 ...

  6. 《深入java虚拟机》读书笔记之Java内存区域

    前言 该读书笔记用于记录在学习<深入理解Java虚拟机--JVM高级特性与最佳实践>一书中的一些重要知识点,对其中的部分内容进行归纳,主要是方便之后进行复习. 运行时数据区域 Java虚拟 ...

  7. Java并发读书笔记:线程安全与互斥同步

    目录 导致线程不安全的原因 什么是线程安全 不可变 绝对线程安全 相对线程安全 线程兼容 线程对立 互斥同步实现线程安全 synchronized内置锁 锁即对象 是否要释放锁 实现原理 啥是重进入? ...

  8. java effective 读书笔记

    java effective 读书笔记 []创建和销毁对象 静态工厂方法 就是“封装了底层 暴露出一个访问接口 ” 门面模式 多参数时 用构建器,就是用个内部类 再让内部类提供构造好的对象 枚举 si ...

  9. 读书笔记-浅析Java运行时数据区

    作为一个 Java 为主语言的程序员,我偶尔也需要 用 C/C++ 写程序,在使用时让我很烦恼的一件事情就是需要对 new 出来的对象进行 delete/free 操作,我老是担心忘了这件事情,从而导 ...

随机推荐

  1. 为什么要用docker

    一:更高效的利用系统资源            由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker 对系统资源的利用率更高.无论是应用执行速度.内存损耗或者文件存储速度,都要比传统 ...

  2. PyCharm导入tensorflow包

    若是你也遇到这个问题,说明你也没有理解tensorflow到底在哪里. 当安装了anaconda3.6后,在PyCharm中设置interpreter,这个解释器决定了你在PyCharm环境中写的代码 ...

  3. zabbix安装源

    使用zabbix安装源可以避免版本不同的问题,自己根据自己的需求选择对应的版本即可 http://repo.zabbix.com/zabbix/

  4. mac 版本navicate 如何安装破解版

    https://www.jianshu.com/p/f42785e55b6b  博客地址 部分童鞋安装后没有rpk文件,我也不知道怎么解决实在不行,请下载破解版链接:https://pan.baidu ...

  5. Yii2 设计模式——工厂方法模式

    工厂方法模式 模式定义 工厂方法模式(Factory Method Pattern)定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个.工厂方法让类吧实例化推迟到子类. 什么意思?说起来有这么 ...

  6. Python学习:列表、元组、字典、集合

    转载:https://www.cnblogs.com/xc-718/p/9632942.html 列表/元组 列表和元组都是序列结构,它们本身很相似,但又有一点不同: 列表是用方括号标记,如:a=[1 ...

  7. sql调优2

    今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只是DBA才需要担心的事,而这更是我们程序员需要去关注的事情.当我们去设计数据库表结构,对操作数据 ...

  8. C# 重写Equals

    public class PerformanceRank { public int Rank { get; set; } public string Eid { get; set; } public ...

  9. JSON格式字符串作为存储过程参数解析

    1.新建可编程性的表值函数(SQLSERVER) USE [xxxx] GO /****** Object: UserDefinedFunction [dbo].[parseJSON] Script ...

  10. php验证地图坐标在某片坐标区域内

    mysql空间查询并不太适合地图坐标,如果使用:http://www.cnblogs.com/tyjsjl/p/8760002.html的方式进行地图点坐标的查询就不好用了,于是直接使用php来进行地 ...