1.概述

java不在需要开发人员显示的分配内存和回收内存,而是由JVM自动管理内存的分配和回收(又称为垃圾回收-GC),这简化了编程难度,但同时可能使得程序员在不知不觉中浪费了很多内存,导致JVM花费很多时间进行垃圾回收。另外还有可能由于不清楚JVM的内存分配和回收机制造成内存泄露。最终导致JVM内存不够用。

2.内存区域分类

在JVM规范中,将内存空间分为:方法区(METHOD AREA)、(HEAP)、本地方法栈(NATIV METHOD STACK)、PC寄存器(PROGRAM COUNTER REGISTER)、JAVA栈(JAVA STACK)。

1.方法区(全局共享)

方法去是堆的一个组成部分,他主要存储的是运行时的常量池、静态字段信息、方法信息、构造方法、普通函数的字节码以及一些特殊方法。当虚拟机装载某个类文件时,它使用类装载器定位相应的class文件,然后读入这个class文件内容并把它传输到虚拟机中。由于运行类该类信息会直接加载到内存,所以都是相对较早进入内存中的。方法区的堆和和常规对象存储堆有所区别。部分虚拟机规范不强制要求自动实现内存管理系统,即便有也是放置在永久代的堆中。

运行时常量池:在JVM规范中是这样定义运行时常量池这个数据结构的:Runtime Constant Pool代表运行时每个class文件的常量表。它包含几种常量:编译期的数字常量、方法和域的引用(在运行时解析)。它的功能类似于传统编程语言的符号表,尽管它包含的数据比典型的符号表要丰富得多。每个Runtime Constant Pool都是在JVM的Method area中分配的,每个Class或者Interface的Constant Pool都是在JVM创建class或接口时创建的。它是属于方法区的一部分,所以它的存储也受方法区的规范约束,如果常量池无法分配,同样会抛出OutOfMemoryError。

2.堆(全局共享)

Java堆是java虚拟机所管理内存中最大的一块。java堆是被所有线程共享的一块内存区域,在虚拟机启动创建。此内存区域的唯一目的就是存放对象实例,几乎所有对象实例都在此分配内存。Java堆可以处理物理上不连续的内存空间,只要逻辑上是连续的即可。如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMenoryError异常。因此Java堆是垃圾收集管理器(GC)的主要区域。JAVA堆中的内存释放是不受开发人员控制的,完全由JAVA虚拟机一手操办。对于JAVA虚拟机如何实现垃圾搜集器,JAVA虚拟机规范没有明确的规定,也正因如此,我们平时使用的JAVA虚拟机中提供了许多种垃圾搜集器,它们采用不同的算法以及实现方式,已满足多方面的性能需求。

年轻代(Young Generation)
大多数情况下Java程序中新建的对象都是从新生代分配内存的(注意,大对象可以直接在老年代分配)。新生代由Eden Space和两块相同大小的Survivor Space(通常又称为S0和S1或From和To)构成。而Eden区采用的复制回收算法,此算法在存活对象比例很少的情况下非常高效。当年轻代需要回收时会触发Minor GC(也称作Young GC)。

老年代(Old Generation)
老年代用于存放在年轻代中经多次垃圾回收仍然存活的对象,可以理解为比较老一点的对象,例如缓存对象;新建的对象也有可能在老年代上直接分配内存,这主要有两种情况:一种为大对象,另一种为大的数组对象,且数组对象中无引用外部对象。当老年代满了的时候就需要对老年代进行垃圾回收,老年代的垃圾回收称作Major GC(也称作Full GC)。

内存堆分配配置:

-Xmx :来表示堆的最大大小。默认为物理内存的1/4但小于1GB。

-Xms :来表示堆的最小大小。默认为物理内存的1/64但小于1GB。

-XX:MinHeapFreeRatio=”比例” 当空余堆内存大于”比例”(默认70%)时,JVM会减小到-Xms制定的大小。

-XX:MaxHeapFreeRatio=”比例” 当空余堆内存小于“比例”(默认40%)时,JVM会增大Heap到-Xmx指定的大小。

为了避免频繁的调整Heap的大小。通常将-Xms和-Xmx大小设为一致。

-Xmn :参数来指定新生代的大小。

-XX:SurvivorRadio 调整Eden Space和Survivor Space大小。

-Xss :每个线程可使用的内存大小。

和 -Xms两个选项来控制大小,Xmx,表示初始大小。
-Xmm参数来指定新生代的大小。

3.本地方法栈(线程独有)

本地方法栈是一个传统的栈,它用来支持native方法的执行。如果JAVA虚拟机是使用的其它语言实现指令集解释器的时候,也会用到本地方法栈。如果前面这两种都未发生,也就是说如果JAVA虚拟机不依赖于本地方法栈,而且JAVA虚拟机也不支持native方法,则不需要本地方法栈。而如果需要的话,则本地方法栈也是随每一个线程的启动而创建的。

4.PC寄存器(线程独有)

程序计数器是一个比较小的内存区域,可能是CPU寄存器或者操作系统内存,其主要用于指示当前线程所执行的字节码执行到了第几行,可以理解为是当前线程的行号指示器。字节码解释器在工作时,会通过改变这个计数器的值来取下一条语句指令。 每个程序计数器只用来记录一个线程的行号,所以它是线程私有(一个线程就有一个程序计数器)的。

如果程序执行的是一个Java方法,则计数器记录的是正在执行的虚拟机字节码指令地址;如果正在执行的是一个本地(native,由C语言编写完成)方法,则计数器的值为Undefined,由于程序计数器只是记录当前指令地址,所以不存在内存溢出的情况,因此,程序计数器也是所有JVM内存区域中唯一一个没有定义OutOfMemoryError的区域。

5.JAVA虚拟机栈(线程独有):

JAVA虚拟机栈是在创建线程的同时创建的,用于存储栈帧,JAVA虚拟机栈也是线程独有的。

栈帧:简单点说,可以解释为是一个方法运行时,临时数据的存储区域,具体点说,它里面包括了数据和部分的过程结果,与此同时,它又肩负着处理方法返回值、动态链接以及异常分派的任务。栈帧是随着方法的创建而创建,随着方法的结束而销毁,如果方法抛出异常,也算方法结束。然而在每一个栈帧中,都有着自己的局部变量表以及操作数栈以及对当前类的运行时常量池的引用。

局部变量表:它是一个方法局部变量的列表,是在编译时期就写入了class文件当中。简单的理解,可以将它理解为一个对象数组,而里面按照索引0到length-1分别对应于每一个局部变量,特别的,如果是实例方法的局部变量表,第0个局部变量会是一个指向当前实例的引用,也就是this关键字,其余的局部变量则从索引1开始。

操作数栈:它是一个后进先出(LIFO)栈,而它的长度也是在编译时期就写入了class文件当中,是固定的。它的作用就是提供字节码指令操作变量计算的空间,比如简单的,对于int a=9这句话来说,就需要先将9压入操作数栈,再将9赋给a这个变量。

JVM内存管理概述的更多相关文章

  1. JVM内存管理概述与android内存泄露分析

    一.内存划分 将内存划分为六大部分,分别是PC寄存器.JAVA虚拟机栈.JAVA堆.方法区.运行时常量池以及本地方法栈. 1.PC寄存器(线程独有):全称是程序计数寄存器,它记载着每一个线程当前运行的 ...

  2. 现代JVM内存管理方法的发展历程,GC的实现及相关设计概述(转)

    JVM区域总体分两类,heap区和非heap区.heap区又分:Eden Space(伊甸园).Survivor Space(幸存者区).Tenured Gen(老年代-养老区). 非heap区又分: ...

  3. JVM内存管理------垃圾搜集器参数精解

    本文是GC相关的最后一篇,这次LZ只是罗列一下hotspot JVM中垃圾搜集器相关的重点参数,以及各个参数的解释.废话不多说,这就开始. 垃圾搜集器文章传送门 JVM内存管理------JAVA语言 ...

  4. java虚拟机学习-JVM内存管理:深入垃圾收集器与内存分配策略(4)

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 说起垃圾收集(Garbage Collection,下文简称GC),大部分人都把这项 ...

  5. java虚拟机学习-JVM内存管理:深入Java内存区域与OOM(3)

    概述 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝又 ...

  6. JVM内存管理及GC机制

    一.概述 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代码,对内存泄露 ...

  7. JVM内存管理之垃圾搜集器参数精解

    本文是GC相关的最后一篇,这次LZ只是罗列一下hotspot JVM中垃圾搜集器相关的重点参数,以及各个参数的解释.废话不多说,这就开始. 垃圾搜集器文章传送门 JVM内存管理------JAVA语言 ...

  8. java jvm内存管理/gc策略/参数设置

    1. JVM内存管理:深入垃圾收集器与内存分配策略 http://www.iteye.com/topic/802638 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想 ...

  9. JVM内存管理:深入Java内存区域与OOM

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝 ...

随机推荐

  1. 教你如何用Meterpreter渗透Win系统

    在这篇文章中,我们将跟大家介绍如何使用Meterpreter来收集目标Windows系统中的信息,获取用户凭证,创建我们自己的账号,启用远程桌面,进行屏幕截图,以及获取用户键盘记录等等. 相关Payl ...

  2. Web Scraping with Python

    Python爬虫视频教程零基础小白到scrapy爬虫高手-轻松入门 https://item.taobao.com/item.htm?spm=a1z38n.10677092.0.0.482434a6E ...

  3. GO语言的进阶之路-面向对象编程

    GO语言的进阶之路-面向对象编程 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 当你看完这篇文章之时,我可以说你的Golang算是入门了,何为入门?就是你去看Docker 源码能看 ...

  4. linux下编译出现tmp空间不足解决办法

    编译的时候出现问题: fatal error: error writing to /tmp/ccHqgMoi.s: No space left on device 原因 : 系统 /tmp/空间不足, ...

  5. javascript 5秒后关闭广告案例

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. Mac下IntelliJ IDEA快捷键大全

    Mac键盘符号和修饰键说明⌘ Command⇧ Shift⌥ Option⌃ Control↩︎ Return/Enter⌫ Delete⌦ 向前删除键(Fn+Delete)↑ 上箭头↓ 下箭头← 左 ...

  7. .NET 单点登录开源项目

    1. https://www.apereo.org/cas/client-integration 2.源码下载 https://wiki.jasig.org/display/CASC/.Net+Cas ...

  8. luogu P2303 [SDOi2012]Longge的问题

    传送门 \[\sum_{i=1}^{n}\gcd(i,n)\] 考虑枚举所有可能的gcd,可以发现这一定是\(n\)的约数,当\(\gcd(i,n)=x\)时,\(gcd(\frac{i}{x},\f ...

  9. HDU1875 畅通工程再续【最小生成树】

    题意: 在这些小岛中建设最小花费的桥,但是一座桥的距离必须在10 -- 1000之间. 思路: 用最小生成树解决吧,就那两个算法. 代码: prim #include <iostream> ...

  10. java字符串集合

    一,java的接口跟C语言所能做到的相比确实是让人眼前一亮的东西.利用接口可以将多种东西放到一起,在编程过程中就能省略掉相同类的很多重复代码,将代码进行分类别的,统一的处理. 二,java中的字符串处 ...