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的对象包括以下几种:

  1. 虚拟机栈中引用的对象
  2. 方法区中类静态熟悉引用的对象
  3. 方法区中常量引用的对象
  4. 本地方法栈中JNI引用的对象

JVM垃圾收集算法

标记——清除算法

  首先标记出所有需要回收的对象,在标记完成后统一回收。

  缺点:这种回收算法会产生大量不连续的内存碎片。以后程序运行过程中产生较大的对象时,无法找到足够连续的内存 而不得不提前触发另一次垃圾收集动作。

复制算法

  将内存按容量划分大小相等的两块,每次只使用一块。当这一块的内存用完了,就将还存活的对象复制到另外一块内存上面。

  缺点:将内存的使用率缩小了一半

标记——整理算法

  首先标记出所有需要回收的对象,然后让所有存活的对象都向一端移动。然后直接清理掉端边界以外的内存

分代收集算法

  我们jdk采用的应该就是分代收集算法。根据对象存活周期的不同将内存划分为几块,针对每一块使用不同的算法

  新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要对少量存活的对象复制就可以进行收集。

  老年代中(新生代中经过多次垃圾回收仍然存活的对象,例如缓存对象),因为对象存货率高,没有额外空间对它进行分配担保,就需要使用 标记——整理或者标记——清除算法。

基于JVisualVM的可视化监控

jdk的安装目录bin文件下有jvisualvm.exe可执行文件。可以用来监控虚拟机的性能和故障处理。

这款JDK自带用来监控内存的可视化工具的详细使用,更新中。。。。。。

JVM内存分配和垃圾收集策略的更多相关文章

  1. 【007】【JVM——内存分配和恢复策略】

     内存分配与收回策略 JVM的自己主动内存管理要自己主动化地解决两个问题:对象分配内存以及回收分配给对象的内存.回收内存前几篇已经讲了.如今说内存分配.对象的内存分配一般分配在堆内存中,也可能经过 ...

  2. JVM内存模型及垃圾收集策略解析(一)

    JVM内存模型是Java的核心技术之一,之前51CTO曾为大家介绍过JVM分代垃圾回收策略的基础概念,现在很多编程语言都引入了类似Java JVM的内存模型和垃圾收集器的机制,下面我们将主要针对Jav ...

  3. JVM内存模型以及垃圾收集策略解析

    http://xmuzyq.iteye.com/blog/599750 一 JVM内存模型 1.1 Java栈 Java栈是与每一个线程关联的,JVM在创建每一个线程的时候,会分配一定的栈空间给线程. ...

  4. JVM内存模型及垃圾收集策略解析

    一 JVM内存模型 1.1 Java栈 Java栈是与每一个线程关联的,JVM在创建每一个线程的时候,会分配一定的栈空间给线程.它主要用来存储线程执行过程中的局部变量,方法的返回值,以及方法调用上下文 ...

  5. jvm内存分配和回收策略

    在上一篇中,已经介绍了内存结构是什么样的. 这篇来介绍一下 内存是怎么分配的,和怎么回收的.(基本取自<深入理解Java虚拟机>一书) java技术体系中所提倡的自动内存管理最终可以归结为 ...

  6. JVM 内存分配和回收策略

    对象的内存分配,主要是在java堆上分配(有可能经过JIT编译后被拆为标量类型并间接地在栈上分配),如果启动了本地线程分配缓冲,将按线程优先在TLAB上分配.少数情况下也是直接分配到老年代,分配规则不 ...

  7. A4. JVM 内存分配及回收策略

    [概述] Java 技术体系中所提倡的自动内存管理最终可以归结为自动化地解决两个问题:给对象分配内存以及回收分配给对象的内存. 对象的内存分配,往大方向讲,就是在堆上分配,对象主要分配在新生代的 Ed ...

  8. JVM——内存分配与回收策略

    1.对象优先在Eden区分配 大多数情况下,对象在新生代Eden区分配.当Eden区没有足够的空间进行分配时,虚拟机将发起一次Minor GC. 虚拟机提供了 -XX:+PrintGCDetails这 ...

  9. JVM内存分配与回收策略

    对象优先在Eden分配 大多数情况下,对象在新生代Eden区中分配. 当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC. Minor GC:新生代GC,指发生在新生代的垃圾收集动作 ...

随机推荐

  1. vim 中文乱码怎么解决

    一般来说只需要正确设置vim的编码识别序列就很少会遇到乱码问题: set fileencodings=ucs-bom,utf-8,utf-16,gbk,big5,gb18030,latin1 这个设置 ...

  2. java用POI操作excel——随便写一下,最基础的东西

    前两天部门实施在做一个东西,需要把客户放在Excel中的数据导入到Oracle数据库中,我就想着直接写一个模板,必要的时候改一下实体类应该可以解放实施同事的双手,不过在实际写的过程中,还是碰到很多问题 ...

  3. java分布式电子商务云平台b2b b2c o2o需要准备哪些技术??

    技术解决方案 开发语言: java.j2ee 数据库:mysql JDK支持版本: JDK1.6.JDK1.7.JDK1.8版本 核心技术:分布式.云服务.微服务.服务编排等. 核心架构: 使用Spr ...

  4. web安全之机器学习入门——3.1 KNN/k近邻

    目录 sklearn.neighbors.NearestNeighbors 参数/方法 基础用法 用于监督学习 检测异常操作(一) 检测异常操作(二) 检测rootkit 检测webshell skl ...

  5. 《修炼之道:.NET开发要点精讲》读书笔记(一)

    CLR 公共语言运行库 没有CLR的存在,就不能讲该中间件转换成对应操作系统中的机器指令. 程序集是非完全编译的产物,它兼备了源代码和本地代码的特性,是一种介于源代码和本地代码之间的独立存在的一种数据 ...

  6. 非root用户安装cuda和cudnn

    1.根据自己的系统在官网下载cuda (选择runfile(local)) https://developer.nvidia.com/cuda-downloads 2.进入下载目录,并执行 sh cu ...

  7. python 实现快排序

    def q_sort(arr): if len(arr)<2: return arr pivot = arr[0] less = [x for x in arr[1:] if x <= p ...

  8. 描点的改进:运用chart画图。

    主要是利用Chart画图: 通过选中一部分曲线进行图像的放大和缩小,最小值为1格. 先计算最大值和最小差值.然后赋值给AxisY.Minimum 和AxisY.Maximum.x轴初始显示数目:Axi ...

  9. H5新特性-canvas绘图--渐变对象路径(最复杂)--图片--变形操作

    今天的目标 3.1:canvas绘图--(重点掌握:渐变对象.路径.图片.变形) 3.2:canvas绘图--渐变对象 线性渐变: linearGradient 径向渐变: var g = ctx.c ...

  10. 第五周助教工作总结——NWNU李泓毅

    第五周助教总结 注:因第四次实验安排两个标准时间完成,因此本周未提交完整作业. 本周心得: 第四次实验进行过半,八组同学都在实验课上进行了一次中期总结,并形成书面总结在微信群中讨论. 根据各组同学的中 ...