`
willsunforjava
  • 浏览: 167894 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JAVA内存区域学习笔记

    博客分类:
  • JVM
 
阅读更多

最近看了周志明的《深入理解java虚拟机》一书,看到java内存区域与内存溢出异常一章,颇有收获,现将学习笔记整理如下。

对于java程序员来说,有了JVM的内存管理的帮助,不再需要为每一个对象的创建和销毁进行人工处理。JVM的内存管理使程序不容易出现内存泄露和内存溢出的问题,在C++程序员看来这是一件多么好的事情。但是再好的魔术师也有失手的时候,一旦出现内存问题,就必须了解其本质原理才能解决问题。因此就像书中作者所说,对于C++与java来说,这是一堵“围墙”。

 

1. 运行时数据区域

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

 

 

 

1.1 程序计数器

程序计数器(Program Counter Register)是一块较小的内存空间,它的作用可以看做是单签线程所执行的字节码的行号指示器。在虚拟机的概念模型中,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。其实此时可以讲JVM理解为一台计算机,它的解析指令就是一行一行的字节码,类似于计算机的程序计数器PC。

由于java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的的方式来实现的,在任何一个确定的时刻,一个只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,称这类内存区域为“线程私有”的内存。

如果线程正在执行的是一个java方法,这个计数器记录的是正字执行的虚拟机字节码指令的地址;如果正在执行的是Native方法,这个计数器值侧位空。此内存区域是唯一一个在JVM规范中没有规定任务OOME(OutOfMemoryError)情况的区域。

1.2 Java虚拟机栈

java虚拟机栈(Java Virtual Machine Stacks)也是线程私有的。虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法被调用直至执行完成的过程,就是对应着一个栈帧在VM Stack中从入栈到出栈的过程。

局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。

1.3 本地方法栈

本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则是为虚拟机使用到的Native方法服务。虚拟机规范中队本地方法栈设计没有强制规定,因此具体的虚拟机可以自由实现它。有的虚拟机(如Sun HotSpot)直接就把本地方法栈和虚拟机栈合二为一。

1.4 Java堆

Java堆是被所有现场共享的一块内存区域,在虚拟机启动时创建,此内存区域的唯一目的就是存放对象实例,几乎素有的对象实例都在这里分配内存(“几乎”是因为不完全是)。

如果从内存回收的角度看,由于现在收集器基本都是采用的分代收集算法,所以Java堆还可以细分为:新生代和老生代;如果从内存分配的角度看,线程共享的Java堆中可能划分出多个线程私有的分配缓冲区。无论如何划分,存储的仍都是对象实例,进一步划分的目的是为了更好地回收内存,或者更快地分配内存。

1.5 方法区

方法区(Method Area)也是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器后的代码等数据。可以理解Method Area为Heap的一个逻辑部分。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载。

1.6 运行时常量池

运行时常量池(Runtimely Constant Pool)是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等信息外,还有一项是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。

运行时常量池相对于Class文件常量池的另外一个重要特征是具备动态性,Java并不要求常量一定只能在编译期产生,也就是并非预置入Class文件中常量池的内容才能进入运行时常量池,运行期间也可能将新的常量放入池中,这种特性被开发人员利用的较多的便是String类的intern方法。

1.7 直接内存

直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但是这部分内存也可能导致OOME出现。

在JDK1.4 中新加入了NIO类,引入了一种基于通道(Channel)与缓冲区的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。

2 对象访问

Java的对象访问涉及到JAVA栈、JAVA堆、方法区这三个最重要的内存区域之间的关联关系。如下面的这句代码

Object obj  = new Object();

假设这句代码出现在方法体重,“Object obj”这部分的语义将会反映到Java栈中的本地变量表中,作为一个reference类型数据出现。而“new Object()”这部分的语义将会反映到Java堆中,形成存储Object类型所有实例数据(Instance Data)。另外,在Java堆中还必须包含能查找此对象的类型数据(如对象类型、父类、方法等Class Data)的地址信息,这些Class Data保存在方法区中。

不同虚拟机实现的队形访问方式有所不同,主流的访问方式有两种:使用句柄和直接指针。



 如果使用句柄方式访问,Java堆中将会划分出一块内存作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了Instance Data和Class Data的具体地址信息。


 如果使用直接指针方式访问,Java堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,reference中直接存储的就是对象地址。

 

这两种对象的访问方式各有优势,通过句柄访问方式的最大好处就是reference中存储的是稳定的句柄地址,在对象呗移动时只会改变句柄中的实例数据指针,而reference本身不需要被修改。

使用直接指针访问方式的最大好处就是速度快,它节省了一次指针定位的时间开销,由于对象的访问在Java中非常频繁,因此这类开销积少成多后也是一项非常可观的执行成本。

 

 

 

 

  • 大小: 61.3 KB
  • 大小: 22.7 KB
  • 大小: 20.4 KB
2
3
分享到:
评论
1 楼 a123159521 2012-08-03  
介绍的比较详细,
如果使用直接指针方式访问,Java堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,reference中直接存储的就是对象地址。

现在的jdk使用的就是这种方式.

相关推荐

    Java堆栈内存分析笔记

    堆和栈是Java内存管理的两个主要区域,它们各自承担着不同的职责。本笔记将深入探讨这两个区域的工作原理以及如何进行有效的分析。 首先,我们要理解Java内存的两个主要部分:堆(Heap)和栈(Stack)。堆主要用于...

    Java 虚拟机学习笔记:Java 内存区域,垃圾收集,内存分配与回收策略,JVM 调优,文件结构,类加载机制,Java 程序

    Java 虚拟机学习笔记: Java 内存区域, 垃圾收集, 内存分配与回收策略, JVM 调优, 文件结构, 类加载机制, Java 程序 Java是一种面向对象的编程语言,由Sun Microsystems于1995年推出。它是一种跨平台的语言,...

    Java编程思想学习笔记

    在讨论Java编程思想学习笔记时,首先需要了解的是Java语言的平台无关性,而这一特性正是通过Java虚拟机(JVM)得以实现的。JVM作为Java程序设计的关键组成部分,对于Java开发人员来说是必须掌握的基础知识。在该学习...

    良葛格Java学习笔记

    【良葛格Java学习笔记】 本笔记主要涵盖了Java编程语言的核心概念和技术,旨在帮助初学者以及有一定基础的开发者深入理解并掌握Java。Java作为一种广泛应用于企业级应用开发、移动开发(尤其是Android)以及大数据...

    java精华学习笔记

    Java精华学习笔记主要涵盖了Java编程语言的核心概念、关键特性以及实战技巧。这些笔记是作者在深入学习Java过程中积累的经验总结,旨在帮助初学者快速理解和掌握Java编程。 1. **Java基础** - **数据类型**: Java...

    Java学习笔记_内存管理.rar

    这份"Java学习笔记_内存管理.pdf"很可能是详细解析了Java如何进行内存分配、垃圾回收以及内存泄漏等相关概念。下面,我们将深入探讨Java内存管理的一些核心知识点。 1. **Java内存模型**: - **堆内存(Heap)**:...

    阿里P8 架构师整理Java学习笔记.pdf

    ### Java学习笔记知识点总结 #### 一、JVM与内存管理 **1.1 JVM基本概念** - **JVM(Java Virtual Machine)**: Java虚拟机是执行Java字节码的虚拟机,它提供了运行Java程序所需的环境。 **1.2 线程** - **线程...

    java私塾学习笔记整理

    ### Java私塾学习笔记整理 #### 第一章:Java入门 **一、Java是什么?** Java是一种广泛使用的高级编程语言,由Sun Microsystems于1995年推出。它旨在为跨平台开发提供一种通用的语言环境,使开发者能够在任何...

    JVM内存管理学习笔记

    《JVM内存管理学习笔记》 在Java世界中,JVM(Java Virtual Machine)是运行所有Java应用程序的核心。深入理解JVM内存管理对于优化程序性能、预防和解决内存泄漏问题至关重要。本文将从JVM内存模型、内存区域划分、...

    JAVA学习笔记详解

    ### JAVA学习笔记详解 #### 第一讲 Java语言概述 ##### 课前思考: 1. **新的编程语言是否需要借鉴以前的编程语言?** - 新的编程语言在设计时往往会借鉴已有语言的成功经验和失败教训。Java 作为一种相对较新的...

    java学习笔记文档

    Java学习笔记文档是一份专为初学者准备的宝贵资料,旨在提供系统且实用的Java编程知识。这份文档可能包含了从基础语法、数据类型到高级特性的全面讲解,旨在帮助新手快速掌握这门强大的编程语言。 首先,Java的基础...

    C语言内存相关学习笔记

    ### C语言内存相关学习笔记 #### 一、程序为什么需要内存? ##### 1. 冯诺依曼结构与哈佛结构 - **冯诺依曼结构**:这种结构下的计算机将指令和数据统一存储在同一个存储空间中。这意味着,无论是程序指令还是...

    长期总结的java学习笔记

    此外,Java程序内存区域分为堆、栈和方法区,分别存储不同类型的变量。 在面向对象编程中,类(class)是对象(object)的模板,描述了一类事物的共性,而对象则是类的具体实例。Java中的"=="运算符比较内存地址,...

    Java分布式应用学习笔记-谈JVM.doc

    【Java分布式应用学习笔记-谈JVM】 在Java分布式应用中,JVM(Java虚拟机)扮演着至关重要的角色。虽然有些人可能认为分布式系统与JVM的关系并不密切,但事实上,尤其是在大型分布式环境,如云计算服务平台,对Java...

    Java +学习笔记

    了解JVM的内存区域(如堆、栈、方法区等)和垃圾收集机制,对于优化程序性能和避免内存泄漏至关重要。 以上知识点构成了Java初学者的基础学习路径。通过深入理解并实践这些概念,你将能够熟练地使用Java进行软件...

    java学习笔记之大鹏JAVA终级总结

    Java学习笔记之大鹏JAVA终级总结,是针对Java编程语言深入学习和面试准备的一份综合资料。这份总结涵盖了从基础知识到高级概念的多个方面,旨在帮助初学者理解和掌握Java的核心概念,同时解决面试中可能出现的关键...

    java中间件学习笔记

    以上只是Java中间件学习笔记的部分概述,实际学习中还需要深入理解每个技术的细节,如故障切换逻辑、数据一致性策略、性能调优等,以应对不同场景的需求。对于Java开发者来说,熟练掌握这些中间件技术,能够提升开发...

    java面试,基础学习笔记

    这份"java面试,基础学习笔记"包含了针对面试者复习和初学者学习的关键知识点,旨在帮助你深入理解和掌握Java的核心概念。 在"core_java"部分的学习笔记中,你将深入探讨Java的基础语法和核心特性。这包括但不限于:...

Global site tag (gtag.js) - Google Analytics