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

深入了解Java运行时的内存区域

 
阅读更多
对于java程序员来说,并不必显示地对内存进行管理,一切都交给java虚拟机去做吧,而且,你也不一定做得比java虚拟机来得专业。好像所有内存管理都交给虚拟机去做就万事大吉了,但是,事实有时并非如此,可能有时你会遇到一些让你困惑的问题,如OutOfMemoryError异常,如stackOverflowError,你开始大呼,虚拟机不是都为我们管理好内存了吗?怎么还会出现这样的Error,其实当你真正去了解java虚拟机内存区域的分布的时候,你就会不自觉的大呼:原来java虚拟机也不是万能。   如下图: [img][/img]   这是从网上找到的一个java运行时数据区域,主要包括了方法区(Method Area),java栈区(java stack),本地方法栈区(native method),堆(heap)和程序计数器(program counter register),其中,和java垃圾回收器打交道最多的就是堆了,下面我们就它们的作用分别简述一下:   1.程序计数器(Program Counter Register):   每一个Java线程都有一个程序计数器来用于保存程序执行到当前方法的哪一个指令,对于非Native方法,这个区域记录的是正在执行的VM原语的地址,如果正在执行的是Natvie方法,这个区域则为空(undefined)。此内存区域是唯一一个在VM Spec中没有规定任何OutOfMemoryError情况的区域。   2.Java虚拟机栈(Java Virtual Machine Stacks)   与程序计数器一样,VM栈的生命周期也是与线程相同。VM栈描述的是Java方法调用的内存模型:每个方法被执行的时候,都会同时创建一个帧(Frame)用于存储本地变量表、操作栈、动态链接、方法出入口等信息。每一个方法的调用至完成,就意味着一个帧在VM栈中的入栈至出栈的过程。   3.本地方法栈(Native Method Stacks)   本地方法栈与VM栈所发挥作用是类似的,只不过VM栈为虚拟机运行VM原语服务,而本地方法栈是为虚拟机使用到的Native方法服务。它的实现的语言、方式与结构并没有强制规定,甚至有的虚拟机(譬如Sun Hotspot虚拟机)直接就把本地方法栈和VM栈合二为一。和VM栈一样,这个区域也会抛出StackOverflowError和OutOfMemoryError异常。   对于绝大多数应用来说,Java堆是虚拟机管理最大的一块内存。Java堆是被所有线程共享的,在虚拟机启动时创建。Java堆的唯一目的就是存放对象实例,绝大部分的对象实例都在这里分配。这一点在VM Spec中的描述是:所有的实例以及数组都在堆上分配(原文:The heap is the runtime data area from which memory for all class instances and arrays is allocated),但是在逃逸分析和标量替换优化技术出现后,VM Spec的描述就显得并不那么准确了。   Java堆内还有更细致的划分:新生代、老年代,再细致一点的:eden、from survivor、to survivor,甚至更细粒度的本地线程分配缓冲(TLAB)等,无论对Java堆如何划分,目的都是为了更好的回收内存,或者更快的分配内存。   根据VM Spec的要求,Java堆可以处于物理上不连续的内存空间,它逻辑上是连续的即可,就像我们的磁盘空间一样。实现时可以选择实现成固定大小的,也可以是可扩展的,不过当前所有商业的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制)。如果在堆中无法分配内存,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。上次我们做一个项目的时候,刚开始部署到服务器上的时候,总是出现OutOfMemoryError异常,后来发现,原来jdk1.6默认的堆空间最大是64M,后来我们通过把最大堆值设置大了,解决了这个问题,当然最大堆值不是越大越好,java中允许直接内存进行堆外分配,如果你把堆值设置太大了,那么当剩下的机器内存不足以直接内存的那部分程序使用的话,也会抛出OutOfMemoryError的异常。   5.方法区(Method Area)   方法区中存放了每个Class的结构信息,包括常量池、字段描述、方法描述等等。VM Space描述中对这个区域的限制非常宽松,除了和Java堆一样不需要连续的内存,也可以选择固定大小或者可扩展外,甚至可以选择不实现垃圾收集。相对来说,垃圾收集行为在这个区域是相对比较少发生的,但并不是某些描述那样永久代不会发生GC(至少对当前主流的商业JVM实现来说是如此),这里的GC主要是对常量池的回收和对类的卸载,虽然回收的“成绩”一般也比较差强人意,尤其是类卸载,条件相当苛刻   6.运行时常量池(Runtime Constant Pool)   Class文件中除了有类的版本、字段、方法、接口等描述等信息外,还有一项信息是常量表(constant_pool table),用于存放编译期已可知的常量,这部分内容将在类加载后进入方法区(永久代)存放。但是Java语言并不要求常量一定只有编译期预置入Class的常量表的内容才能进入方法区常量池,运行期间也可将新内容放入常量池(最典型的String.intern()方法)。   运行时常量池是方法区的一部分,自然受到方法区内存的限制,当常量池无法在申请到内存时会抛出OutOfMemoryError异常。   7.本机直接内存(Direct Memory)   直接内存并不是虚拟机运行时数据区的一部分,它根本就是本机内存而不是VM直接管理的区域。但是这部分内存也会导致OutOfMemoryError异常出现,因此我们放到这里一起描述。   在JDK1.4中新加入了NIO类,引入一种基于渠道与缓冲区的I/O方式,它可以通过本机Native函数库直接分配本机内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显着提高性能,因为避免了在Java对和本机堆中来回复制数据。   显然本机直接内存的分配不会受到Java堆大小的限制,但是即然是内存那肯定还是要受到本机物理内存(包括SWAP区或者Windows虚拟内存)的限制的,一般服务器管理员配置JVM参数时,会根据实际内存设置-Xmx等参数信息,但经常忽略掉直接内存,使得各个内存区域总和大于物理内存限制(包括物理的和操作系统级的限制),而导致动态扩展时出现OutOfMemoryError异常。 原文出自【比特网】,转载请保留原文链接:[url=http://soft.chinabyte.com/database/413/12432913.shtml]http://soft.chinabyte.com/database/413/12432913.shtml[/url]
  • 大小: 24 KB
分享到:
评论

相关推荐

    Java运行时内存分配

    综上所述,Java运行时内存分配涉及多个不同的存储区域,每个区域都有其特点和适用场景。理解这些区域及其用途有助于开发者更好地优化代码性能,避免常见的内存泄漏问题。例如,合理地选择对象的存储位置可以显著提高...

    深入理解Java内存模型 pdf 超清版

    - 新建(New)、就绪(Runnable)、运行(Running)、等待(Blocked/Waiting)、阻塞(Timed_Waiting/Terminated)是Java线程的五种状态,了解状态转换有助于理解线程行为。 深入理解Java内存模型,不仅能够帮助...

    深入理解Java 虚拟机内存模型.rar

    了解这些内存区域后,我们还需要关注以下关键概念: - **对象创建与分配**:Java对象通常在堆上创建,通过new关键字或者反射实现。 - **垃圾收集(Garbage Collection, GC)**:自动内存管理,清理不再使用的对象,...

    深入Java核心_Java内存分配原理精讲

    总结,深入理解Java内存分配原理意味着深入理解Java运行机制,这将帮助开发者编写出更高效、更健壮的代码,提升系统的整体性能和稳定性。通过学习和实践,开发者可以更好地应对内存溢出、性能瓶颈等问题,从而成为...

    Java运行内存

    在Java编程环境中,理解Java运行内存是非常关键的,它涉及到程序的性能优化和问题排查。Java虚拟机(JVM)为Java应用程序提供了运行时环境,其中包括了多个内存区域,这些区域各自负责不同的任务,共同保证了程序的...

    深入Java核心 Java内存分配原理精讲

    3. **堆**:是Java中最主要的内存区域,所有通过`new`关键字创建的对象和数组都位于这里。堆由垃圾回收器自动管理,开发者无需手动释放内存。 4. **静态域**:存储在对象中的`static`定义的静态成员,这部分内存由...

    深入理解Java虚拟机(第二版)_java_

    2. 运行时数据区:JVM在内存中划分为若干区域,如堆、栈、方法区、程序计数器和本地方法栈。堆存储对象实例,栈保存方法调用信息,方法区存储类元数据,程序计数器记录下一条要执行的指令地址,本地方法栈服务于Java...

    java中多态的内存分析

    Java程序运行时主要涉及四种内存区域:程序计数器、虚拟机栈、本地方法栈、堆和方法区(在Java 8及以后版本中,方法区被元空间取代)。 1. **程序计数器**:每个线程都有一个独立的程序计数器,用于存储当前线程...

    Java运行内存分析

    Java运行内存分析涉及了Java虚拟机(JVM)内存结构和内存管理的各个方面。JVM内存主要分为以下几个部分:栈内存(Stack)、堆内存(Heap)、方法区(Method Area)、运行时常量池(Runtime Constant Pool)以及直接...

    深入java虚拟机 高清pdf 高清高清高清

    了解这些内存区域的分配与回收机制,有助于避免内存泄漏和提高程序性能。 3. **垃圾收集与内存管理**:Java虚拟机中的垃圾收集机制是自动进行内存管理的关键。书里介绍了不同的垃圾收集算法(如标记-清除、复制、...

    深入Java核心 Java内存分配原理精讲(对于没有接触过java内存的程序员很有用)

    Java内存分配是理解Java运行机制的关键部分,尤其对于初学者而言,掌握这一原理能显著提升编程效率和代码质量。Java内存分配涉及多个区域,包括栈、堆、常量池等,每个区域都有其独特的功能和适用场景。 ### 一、...

    30+个视频+深入理解Java虚拟机(jvm优化+内存模型+虚拟机原理)

    堆是JVM管理的最大块内存区域,用于存储对象实例。堆被划分为新生代和老年代,其中新生代又细分为Eden区和两个Survivor区(S0和S1)。对象首先在Eden区创建,经过几次GC后会被移动到Survivor区,最后可能晋升到老年代...

    深入解读 Java 堆外内存(直接内存)1

    Java 堆外内存,又称直接内存(Direct Memory),是 Java 程序中除JVM堆内存之外的一种内存区域。它并不遵循JVM规范中定义的标准内存模型,而是直接与操作系统交互,用于提高特定场景下的性能,尤其是涉及到大量I/O...

    深入JAVA虚拟机 随书源码 JVM规范

    首先,我们来看《深入JAVA虚拟机》这本书,它涵盖了JVM的各个关键方面,包括指令集、运行时数据区、方法区、堆内存、栈帧结构、编译与优化、异常处理和安全性等。书中通过实例解析,帮助读者理解JVM如何处理Java程序...

    Java 监控 运行时

    Java运行时监控是Java开发和运维过程中至关重要的一个环节,它可以帮助我们理解应用程序在实际运行中的性能、资源消耗以及可能出现的问题。通过对Java应用的实时监控,我们可以及时发现并解决潜在的性能瓶颈,优化...

    【深入Java虚拟机】Java内存模型探讨一.pdf

    Java内存模型,简称JVM内存模型,是Java虚拟机(JVM)运行时的核心组成部分,它定义了如何在多线程环境下共享数据以及确保数据一致性。深入理解Java内存模型对于优化程序性能、避免并发问题至关重要。 首先,让我们...

    java内存模型.pdf

    标题和描述中提及的知识点主要围绕Java内存...总之,深入理解Java内存模型和JVM内存结构对于Java开发者来说至关重要,它不仅有助于编写更高效、更安全的代码,还能在遇到性能瓶颈或内存问题时,快速定位并解决问题。

    深入理解Java虚拟机1

    第二部分“自动内存管理”,详细阐述了Java内存区域的划分,包括堆、栈、方法区、本地方法栈等,并讨论了内存溢出异常的原因和解决方法。同时,该部分介绍了垃圾收集器的工作机制和内存分配策略,帮助开发者理解如何...

Global site tag (gtag.js) - Google Analytics