JVM内存分配和垃圾收集策略
java内存区域

程序计数器
因为java可以多线程并发执行,因此,为了线程切换后能恢复到正确的执行位置,每个线程都需要一个独立的程序计数器。记录正在执行的虚拟机字节码指令的地址。
这个区域不会产生内存溢出异常。
栈
java虚拟机栈
栈中主要存放了编译期可知的四类八种基本数据类型存(逻辑型 boolean、文本型char、整数型byte、short、int、float、浮点数型double、long),对象引用类型,和对象引用类型(reference)。
本地方法栈
本地方法栈和java虚拟机栈所发挥的作用非常相似,他们之前的区别是虚拟机栈为虚拟机执行java方法服务。而本地方法栈是为虚拟机使用到的Native方法服务。
-Xss参数可以设置本地方法栈的内存上限。
如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常。
程序中 递归如果找不到出口也会抛出此异常(不断的进行入栈操作)
堆
用于存放对象的实列
可通过-Xms和Xmx来扩展堆的大小。因为现在的收集器基本都采用分代收集算法,所以java堆中还可以细分:新生代和老年代
如果在堆中没有内存完成实列分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。-Xmx可以设置堆内存的上限 -Xms 可以设置内存初始化的大小
方法区 PermGen space(也称永久代、也叫非堆 )
用于储存已被虚拟机加载的类的信息(编译后的class)、常量、静态变量、即时编译器编译后的代码等数据,Class在被Loader时就会被放到方法区中,加载类的类加载器本身也存在这里。
垃圾收集行为在这个区比较少出现的,有点类似它的名字,永久代
当方法区无法满足内存分配需求时,将抛出OutOfMemoryError(后面会跟PermGen space字符串)异常。-XX:MaxPermSize可以设置方法区的上限。
运行时常量池(方法区的一部分)
用于存放编译期生成的各种字面量和符号的引用,既然运行时常量池是方法区的一部分,自然收到方法区内存的限制,当常量池无法再申请到内存时会抛出OutOfMemoryError异常。
JAVA的String声明的变量就是放在运行时常量池中比如String str="test"; 。
但是 String str=new String("test");是new一个对象 是放在堆中(用new关键字创建字符串常量时,JVM会首先检查字符串常量池,如果字符串不存在常量池中,就会在实例化该字符串(堆中)的同时,在常量池也存放一份)
由于String字符串的不可变性我们可以十分肯定常量池中一定不存在两个相同的字符串
以上
如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常。
如果虚拟机在扩展时无法申请到足够的内存空间,则抛出OutOfMemoryError异常。可通过-Xmx和-XX:MaxPermSize可以设置堆内存和方法区上限。-Xmx2048m -XX:MaxPermSize=512m
把-Xmx 和-Xms大小设置一样内存大小,可以提高JVM的运行性能(取消掉伸缩区)
对象的finalize()方法简介
当垃圾回收器要释放无用对象的内存时,会先调用该对象的finalize()方法。对象的finalize()方法有以下特点
1)垃圾回收是否执行该方法,以及何时执行该方法都是不确定的。
换句话说 以下这种情况是有可能的:一个程序只占用了少量内存,没有造成严重的内存需求,于是垃圾回收器没有释放那些无用对象的内存,因此这些对象的finalize()方法还没有被调用,程序就终止了。
2)finalize()方法有可能使对象复活,使它恢复到可触及状态。
可触及状态:当一个对象 假定A对象被创建后,只要程序中还有引用变量在引用它,那么它就始终处于可触及状态。
可复活状态:当程序不在有任何变量引用A对象时,那么它就进入可复活状态。在这个状态中,垃圾回收期会准备释放它的内存,在释放之前,会调用其他处于可复活状态的finalize()方法,这些finalize()方法有可能使A对象重新转到可触及状态。
不可触及状态:当java虚拟机执行完所有可复活对象的finalize()方法后,假如这些方法都没有使A对象转到可触及状态,那么A对象就进入不可触及状态,垃圾回收才会真正的回收它的内存。
3)垃圾回收器在执行finalize()方法时,如果出现异常,垃圾回收器不会报告异常,程序继续正常执行。
判断对象是否需要回收
引用计数算法
给对象中添加一个引用计数器,每当有一个地方引用他时,计数器值就加1;当引用失效时,计数器值就减一;任何时刻计数器为0的对象就是不可能在被使用的。
这种方法实现简单,判定效率也很高,但是主流的java虚拟机里面没有采用这种方法,因为它很难解决循环引用的问题。
可达性分析算法(主流的商业语言所采用的算法)
这个算法的基本思路就是通过一系列称为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径成为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连(GC Roots到这个对象不可达)时,则证明此对象是不可用的。
在JAVA语言中,可作为GC Roots的对象包括以下几种:
- 虚拟机栈中引用的对象
- 方法区中类静态熟悉引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI引用的对象
JVM垃圾收集算法
标记——清除算法
首先标记出所有需要回收的对象,在标记完成后统一回收。
缺点:这种回收算法会产生大量不连续的内存碎片。以后程序运行过程中产生较大的对象时,无法找到足够连续的内存 而不得不提前触发另一次垃圾收集动作。
复制算法
将内存按容量划分大小相等的两块,每次只使用一块。当这一块的内存用完了,就将还存活的对象复制到另外一块内存上面。
缺点:将内存的使用率缩小了一半
标记——整理算法
首先标记出所有需要回收的对象,然后让所有存活的对象都向一端移动。然后直接清理掉端边界以外的内存
分代收集算法
我们jdk采用的应该就是分代收集算法。根据对象存活周期的不同将内存划分为几块,针对每一块使用不同的算法
新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要对少量存活的对象复制就可以进行收集。
老年代中(新生代中经过多次垃圾回收仍然存活的对象,例如缓存对象),因为对象存货率高,没有额外空间对它进行分配担保,就需要使用 标记——整理或者标记——清除算法。
基于JVisualVM的可视化监控
jdk的安装目录bin文件下有jvisualvm.exe可执行文件。可以用来监控虚拟机的性能和故障处理。

这款JDK自带用来监控内存的可视化工具的详细使用,更新中。。。。。。
JVM内存分配和垃圾收集策略的更多相关文章
- 【007】【JVM——内存分配和恢复策略】
内存分配与收回策略 JVM的自己主动内存管理要自己主动化地解决两个问题:对象分配内存以及回收分配给对象的内存.回收内存前几篇已经讲了.如今说内存分配.对象的内存分配一般分配在堆内存中,也可能经过 ...
- JVM内存模型及垃圾收集策略解析(一)
JVM内存模型是Java的核心技术之一,之前51CTO曾为大家介绍过JVM分代垃圾回收策略的基础概念,现在很多编程语言都引入了类似Java JVM的内存模型和垃圾收集器的机制,下面我们将主要针对Jav ...
- JVM内存模型以及垃圾收集策略解析
http://xmuzyq.iteye.com/blog/599750 一 JVM内存模型 1.1 Java栈 Java栈是与每一个线程关联的,JVM在创建每一个线程的时候,会分配一定的栈空间给线程. ...
- JVM内存模型及垃圾收集策略解析
一 JVM内存模型 1.1 Java栈 Java栈是与每一个线程关联的,JVM在创建每一个线程的时候,会分配一定的栈空间给线程.它主要用来存储线程执行过程中的局部变量,方法的返回值,以及方法调用上下文 ...
- jvm内存分配和回收策略
在上一篇中,已经介绍了内存结构是什么样的. 这篇来介绍一下 内存是怎么分配的,和怎么回收的.(基本取自<深入理解Java虚拟机>一书) java技术体系中所提倡的自动内存管理最终可以归结为 ...
- JVM 内存分配和回收策略
对象的内存分配,主要是在java堆上分配(有可能经过JIT编译后被拆为标量类型并间接地在栈上分配),如果启动了本地线程分配缓冲,将按线程优先在TLAB上分配.少数情况下也是直接分配到老年代,分配规则不 ...
- A4. JVM 内存分配及回收策略
[概述] Java 技术体系中所提倡的自动内存管理最终可以归结为自动化地解决两个问题:给对象分配内存以及回收分配给对象的内存. 对象的内存分配,往大方向讲,就是在堆上分配,对象主要分配在新生代的 Ed ...
- JVM——内存分配与回收策略
1.对象优先在Eden区分配 大多数情况下,对象在新生代Eden区分配.当Eden区没有足够的空间进行分配时,虚拟机将发起一次Minor GC. 虚拟机提供了 -XX:+PrintGCDetails这 ...
- JVM内存分配与回收策略
对象优先在Eden分配 大多数情况下,对象在新生代Eden区中分配. 当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC. Minor GC:新生代GC,指发生在新生代的垃圾收集动作 ...
随机推荐
- Windows服务模式下tomcat开启远程调试
测试环境:windows IDE:IDEA 2018 2.5 x64 按照图示,加以下参数加入配置中 -Xdebug -Xrunjdwp:transport=dt_socket,address=998 ...
- VirtualBox 桥接模式,虚拟机ping不通宿主机
虚拟机为window server 2012 参考链接:https://blog.csdn.net/Leon_190/article/details/84937045#commentBox 该做的都做 ...
- Texture转Texture2D
private Texture2D TextureToTexture2D(Texture texture) { Texture2D texture2D = new Texture2D(texture. ...
- Java 字符编码(一)Unicode 字符编码
Java 字符编码(一)Unicode 字符编码 Unicode(http://www.unicode.org/versions/#TUS_Latest_Version) 是一个编码方案,说白了希望给 ...
- 关于python,完善我计算机知识的一步。
因为身为理科男,所以特别喜欢涉及其他领域的知识.而对我来说,计算机是很有诱惑力的--尤其是程序语言设计,懂得一门“外语”是多么的重要.大一时候接触过包括有计算机的基本知识,c语言,这个新的学期也开始接 ...
- Apache万网SSl证书安装不成功的一个注意事项(https安全链接,基于phpstudy)
最近,微信小程序挺火,要做小程序网站域名必须要有ssl证书,形成https://的安全链接,我于是从万网上下载了一个免费的ssl证书,按照万网提供的安装方式怎么也安装不好,最后我这个Apache小白费 ...
- Linux学习---位运算符
<<.>> ① << 左移 乘以2^n m << n m*(2^n) eg:4: 0 0 1 0 0 8: 0 1 0 0 0 [数据.数字]移位 左 ...
- 学以致用三十一-----IPAddressField has been removed
python 和 django版本 在进行makemigrations的时候报错 设置的字段 class Servers(models.Model): '''服务器信息''' hostname = m ...
- Note | Git
目录 1. 出发 A. 安装 B. 设置机器身份 C. 创建版本(仓)库 repository D. 可管理文件 2. 基础操作 A. 添加文件至仓库 B. 修改文件并查看修改 C. 查看历史变动 D ...
- 【repost】javascript callback
在javascript中回调函数非常重要,它们几乎无处不在.像其他更加传统的编程语言都有回调函数概念,但是非常奇怪的是,完完整整谈论回调函数的在线教程比较少,倒是有一堆关于call()和apply() ...