内存碎片

JVM垃圾回收算法

和自甴很熟 提交于 2020-01-12 05:11:32
1.堆的分代和区域 (年轻代)Young Generation(eden、s0、s1 space) Minor GC (老年代)Old Generation ( Tenured space ) Major GC|| Full GC (永久代)Permanent Generation ( Permanent space )【 方法区(method area) 】 Major GC 本地化的String从JDK 7开始就被移除了永久代(Permanent Generation ) JDK 8.HotSpot JVM开始使用本地化的内存存放类的元数据,这个空间叫做元空间(Metaspace) 2.判断对象是否存活(哪些是垃圾对象) 1.引用计数 (ReferenceCounting) :对象有引用计数属性,增加一个引用计数加1,减少一个引用计数减1,计数为0时可回收。 (无法解决对象相互循环引用的问题) 2. 根搜索 (GC Roots Tracing) : GCRoot对象作为起始点(根)。如果从根到某个对象是可达的,则该对象称为“可达对象”(存活对象,不可回收对象)。否则就是不可达对象,可以被回收。 下图中,对象Object6、Object7、Object8虽然互相引用,但他们的GC Roots是不可到达的,所以它们将会被判定为是可回收的对象 3.垃圾收集算法 1. 标记-清除

java垃圾收集算法介绍

喜欢而已 提交于 2020-01-11 11:54:07
垃圾收集是java中相当重要的一部分,大部分人都把这项技术当作java语言的半生产物。事实上,GC的历史比java久远。本篇文章主要介绍java中的垃圾回收算法,并且由于垃圾收集算法设计大量的程序细节,而且各个平台的虚拟机操作内存的方法又各不相同,所以只是简单介绍。 标记-清除算法 他是java中最基础的收集算法,如同它的名字一样,孙阿法分为“标记”和“清除”两个阶段,首先标记处所有需要回收的对象,在标记完成后统一回收所有被标记的对象。之所以说他是最基础的收集算法是因为后续的收集算法都是基于何种思路并对其不足进行改进而以。 标记-清除算法它的不足有两个:1、效率问题,标记和清除两个过程的效率都不高;2、空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配大对象时,无法找到足够的连续内存而不得不提前出发另一次垃圾收集动作。 标记-清除算法执行过程如下图: 复制算法 复制算法主要为了解决效率问题,他将可用内存按照容量划分为大小相等的两块,每次只使用其中的一块。当这一块内存用完了,就将还存活着的对象复制到另外一块上,然后再把已使用过的内存哦那个贱一次清理掉。这样使得每次都是堆整个半区进行内存回收,内存分配时也就不考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高校。但是这种算法的代价是将内存缩小为原来的一半

操作系统:内存管理(概念)

回眸只為那壹抹淺笑 提交于 2020-01-11 07:40:11
  1、物理地址和逻辑地址    物理地址:加载到内存地址寄存器中的地址,内存单元的真正地址。在前端总线上传输的内存地址都是物理内存地址,编号从0开始一直到可用物理内存的最高端。这些数字被北桥(Nortbridge chip)映射到实际的内存条上。物理地址是明确的、最终用在总线上的编号,不必转换,不必分页,也没有特权级检查(no translation, no paging, no privilege checks)。   逻辑地址:CPU所生成的地址。逻辑地址是内部和编程使用的、并不唯一。例如,你在进行C语言指针编程中,可以读取指针变量本身值(&操作),实际上这个值就是逻辑地址,它是相对于你当前进程数据段的地址(偏移地址),不和绝对物理地址相干。   2、连续内存分配方案:   内存必须容纳操作系统和各种用户进程,因此必须尽可能有效得分配内存,在分配内存过程中,通常需要将多个进程放入内存中,前面提到过,我们需要每个进程的空间相互独立,而且我们必须保护每个进程的内存空间的独立性,如果不同的进程间需要通信,可以按照我们前面提到的通信方法进行通信,但是在此时,我们考虑内存空间独立性的实现。这就涉及到内存分配:   我们将整个内存区域多个固定大小的分区,每个分区容纳一个进程,当一个分区空闲时,可以将内存调入内存,等待执行,这是最简单的内存分配方案,但是这种方案存在很多问题

python 垃圾回收机制

南楼画角 提交于 2020-01-11 05:37:16
1.常见的垃圾回收策略如下 python采用的是引用计数机制为主,标记-清除和分代收集两种机制为辅的策略 1)引用计数 python 引用计数是一种非常高效的内存管理手段,当一个pyhton对象被引用时其引用计数增加1,当其不再被引用时引用计数减1,当引用计数等于0的时候,对象就被删除了。 2)标记清除 ruby 标记清除(Mark—Sweep)』算法是一种基于追踪回收(tracing GC)技术实现的垃圾回收算法。它分为两个阶段:第一阶段是标记阶段,GC会把所有的『活动对象』打上标记,第二阶段是把那些没有标记的对象『非活动对象』进行回收。 标记清除并不像引用计数那样是实时的,而是等待占用内存到达GC阈值的时候才会触发 3)分代收集 jvm 分代回收是一种以空间换时间的操作方式,Python将内存根据对象的存活时间划分为不同的集合,每个集合称为一个代,Python将内存分为了3“代”,分别为年轻代(第0代)、中年代(第1代)、老年代(第2代),他们对应的是3个链表,它们的垃圾收集频率与对象的存活时间的增大而减小。 新创建的对象都会分配在年轻代,年轻代链表的总数达到上限时,Python垃圾收集机制就会被触发,把那些可以被回收的对象回收掉,而那些不会回收的对象就会被移到中年代去,依此类推,老年代中的对象是存活时间最久的对象,甚至是存活于整个系统的生命周期内。 同时

Tomcat参数JAVA_OPTS调整

久未见 提交于 2020-01-10 17:22:25
启动文件修改 在windows环境下,tomcat下的~/bin/catalina.bat文件,在文件头部加入: set "JAVA_OPTS=%JAVA_OPTS% -server -Xms5120m -Xmx10240m -XX:PermSize=640M -XX:MaxPermSize=2560m" 在linux环境下,tomcat下的~/bin/catalina.sh文件,在文件头部加入: JAVA_OPTS = " $JAVA_OPTS -server -Xms4096m -Xmx6144m -XX:PermSize=256m -XX:MaxPermSize=2048m" 重启tomcat,即可。 验证 可以通过访问 http://localhost:8080/manager/status 可以查看jvm的信息。tomcat的管理员配置详见tomcat管理员配置 常用参数详解: - server:一定要作为第一个参数,在多个 CPU 时性能佳,还有一种叫 - client 的模式,特点是启动速度比较快,但运行时性能和内存管理效率不高,通常用于客户端应用程序或开发调试,在 32 位环境下直接运行 Java 程序默认启用该模式。Server 模式的特点是启动速度比较慢,但运行时性能和内存管理效率很高,适用于生产环境,在具有 64 位能力的 JDK 环境下默认启用该模式

《浏览器工作原理与实践》 <13> 垃圾回收:垃圾数据是如何自动回收的?

狂风中的少年 提交于 2020-01-10 14:37:00
不过有些数据被 使用之后,可能就不再需要了 ,我们把这种数据称为 垃圾数据 。如果这些垃圾数据一直保存在内存中,那么内存会越用越多,所以我们需要 对这些垃圾数据进行回收 ,以 释放有限的内存空间 。 不同语言的垃圾回收策略 通常情况下,垃圾数据回收分为 手动回收 和 自动回收 两种策略。 如 C/C++ 就是使用手动回收策略,何时分配内存、何时销毁内存都是由代码控制的,你可以参考下面这段 C 代码: //在堆中分配内存 char* p = (char*)malloc(2048); //在堆空间中分配2048字节的空间,并将分配后的引用地址保存到p中 //使用p指向的内存 { //.... } //使用结束后,销毁这段内存 free(p); p = NULL; 从上面这段 C 代码可以看出来,要使用堆中的一块空间,我们需要先调用 mallco 函数分配内存,然后再使用;当不再需要这块数据的时候,就要手动调用 free 函数来释放内存。如果这段数据已经不再需要了,但是又没有主动调用 free 函数来销毁,那么这种情况就被称为 内存泄漏 。 另外一种使用的是 自动垃圾回收的策略 ,如 JavaScript、Java、Python 等语言,产生的垃圾数据是由垃圾回收器来释放的,并 不需要手动通过代码来释放 。 对于 JavaScript 而言,也正是这个“自动”释放资源的特性带来了很多困惑

JVM垃圾回收算法

守給你的承諾、 提交于 2020-01-10 13:48:11
转:https://www.cnblogs.com/godoforange/p/11552865.html 如何判断对象是否为垃圾对象? 1)引用计数法 在对象中添加一个引用计数器,当有地方引用这个对象的时候,引用技术器得值就+1,当引用失效的时候,计数器得值就-1 算法缺点:循环引用无法回收。 2)可达性分析法 GCroot结点开始向下搜索,路径称为引用链,当对象没有任何一条引用链链接的时候,就认为这个对象是垃圾,并进行回收。 那么什么是GCroot呢(虚拟机在哪查找GCroot)。 虚拟机栈(局部变量表) 方法区的类属性所引用的对象。 方法区中常量所引用的对象。 本地方法栈中引用的对象。 目前主流JVM采用的垃圾判定算法就是可达性分析法。 垃圾回收算法: 1)标记-清除算法 存在的问题: 效率问题。 内存小块过多。 如图所示:黄色的就是被标记清除的。清除后会发现有很多多余的小块。 2)复制算法 下面是java内存常规划分 (线程共有)堆内存 方法区 (栈内存 本地方法栈) 程序计数器 下面是堆内存的划分 新生代 Eden 伊甸园 Survivor 存活区 Tenured Gen 养老区 老年代 下面就是过程: 被标记的黑色就是需要回收的 将白色区域复制下面,然后清空上面的 这样就完成了内存的连续分配,但是引来一个问题。 每次只能使用一半的内存。是不是有点少。。 为了解决这个问题

Java基础之JVM

别等时光非礼了梦想. 提交于 2020-01-10 06:00:26
一、内存模型 1、程序计数器(线程私有) 一块较小的内存空间,是当前线程所指向的字节码的行号指示器。 2、虚拟机栈(线程私有) 是描述java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用直至完成的过程,对应着一个栈帧在虚拟机中入栈到出栈的过程。 栈帧 是用来存储数据和部分过程结果的数据结构,同时也被用来处理动态链接、方法返回值和异常分派。随方法的创建而创建,随着方法结束而销毁 3、本地方法栈(线程私有) 与虚拟机栈作用类似,区别是虚拟机栈为执行java方法服务,而本地方法栈则为Native方法服务。 4、堆(线程共享) 创建的对象和数组都保存在Java堆内存中,也是垃圾收集器进行垃圾手机的最重要的内存区域。现代VM采用分代手机算法,从GC角度还可分为新生代和老年代 5、方法区(线程共享) 即我们说的永久代,用于存储被JVM今安在的类信息、常量、静态变量、即时编译器编译后的代码等数据HotSpot VM把GC分代收集扩展至方法区,即使用Java堆的永久代来实现方法区,这样HotSpot的垃圾收集器就可以像管理java堆一样管理这部分内存,而 不必为方法区开发专门的内存管理器。 运行时常量池 :是方法区的一部分。用于存放编译期生成的各种字面量和符号引用

slab机制解析

好久不见. 提交于 2020-01-09 23:27:42
slab机制解析 引言 1 概述 1.1 kmem_cache 1.2 kmem_cache_node 1.3 page 2 源码解读 引言 slab是Linux在伙伴系统之上的一种内存管理机制。伙伴系统最小的内存处理大小为4k(即一页的内存大小),然而,实际使用内存过程中,很多都是小内存,为了 提高内存申请释放效率 、 防止内存碎片的产生 、 防止内存连续分配导致CPU缓存命中率低 ,linux在伙伴系统之上设计出slab机制来解决这些问题。slab可以理解为它是linux内核的 对象池 。 1 概述 整个slab机制的数据结构如下图。 注1 : page描述符中很多字段是以union形式存在,所以最好结合源码查看。 1.1 kmem_cache kmem_cache缓存对象,每个kmem_cache对应一种object类型。各个字段意义如下: name: 缓存名称; list: 缓存链表,所有的kmem_cache都会连接成一个全局的链表; refcount: 应用计数; object_size:对象大小; align:对象以align个字节对齐; ctor:对象初始化函数指针,可以理解为c++的构造函数; node: 保存kmem_cache_node数组,在NUMA架构中,每个内存节点对应一个缓存节点来分开管理; cpu_cache:为每个cpu变量的对象缓存池

JVM垃圾回收

隐身守侯 提交于 2020-01-08 15:33:53
1. 概念理解 1.1. 并行(Parallel)与并发(Concurrent) 并行:指多个垃圾收集线程并行工作,但此时用户线程仍然处于等待状态 并发:指用户线程与垃圾收集线程同时执行 1.2. Minor GC 与 Major GC Minor GC:指发生在新生代的垃圾收集动作,因为Java对象大多都具备朝生夕灭的特性,所以Minor GC非常频繁,一般回收速度也比较快。 Major GC:指发生在老年代的GC,出现了Major GC,经常会伴随至少一次的Minor GC。Major GC的速度一般会比Minor GC慢10倍以上。 1.3. 吞吐量 吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值,即吞吐量 = 运行用户代码时间 /(运行用户代码时间 + 垃圾收集时间) 假设虚拟机总共运行了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99% 2. 对象存活判断 回收的第一步是标记出哪些需要回收,为此需要有一种方式来判断对象是否存活,存活的不用回收 判断的方式是可达性分析,通过遍历对象的引用树来找出存活的对象 所谓的引用树本质上是有根的图结构,它沿着对象的根句柄向下查找到活着的节点,并标记下来;其余没有被标记的节点就是死掉的节点,这些对象就是可以被回收的 遍历从GC Roots开始,那么哪些对象可作为GC Roots对象? 虚拟机栈中应用的对象