内存管理

ANDROID内存优化(大汇总——上)

跟風遠走 提交于 2019-12-19 18:49:26
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 内存简介: RAM(random access memory)随机存取存储器。说白了就是内存。 一般Java在内存分配时会涉及到以下区域: 寄存器(Registers): 速度最快的存储场所,因为寄存器位于处理器内部 , 我们在程序中无法控制 栈(Stack): 存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中 堆(Heap): 堆内存用来存放由new创建的对象和数组。在堆中分配的内存,由Java虚拟机的自动垃圾回收器(GC)来管理。 静态域(static field): 静态存储区域就是指在固定的位置存放应用程序运行时一直存在的数据,Java在内存中专门划分了一个静态存储区域来管理一些特殊的数据变量如静态的数据变量 常量池(constant pool): 虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的一个有序集和,包括直接常量(string,integer和floating point常量)和对其他类型,字段和方法的符号引用。 非RAM存储: 硬盘等永久存储空间 堆栈特点对比: 由于篇幅原因,下面只简单的介绍一下堆栈的一些特性。 栈 :当定义一个变量时,Java就在栈中为这个变量分配内存空间,当该变量退出该作用域后,Java会自动释放掉为该变量所分配的内存空间

《Glibc内存管理》笔记DAY2

a 夏天 提交于 2019-12-19 04:22:33
目录 Ptmalloc内存管理设计 Main_arena 与 non_main_arena chunk 的组织 空闲 chunk 容器 sbrk 与 mmap 内存分配概述 内存回收概述 边界标记法 内容来源 Ptmalloc内存管理设计 具有长生命周期的大内存分配使用 mmap。 特别大的内存分配总是使用 mmap。 具有短生命周期的内存分配使用 brk,因为用 mmap 映射匿名页,当发生缺页异常时,linux 内核为缺页分配一个新物理页,并将该物理页清 0,一个 mmap 的内存块需要映射多个物理页,导致多次清 0 操作,很浪费系统资源,所以引入了 mmap分配阈值动态调整机制,保证在必要的情况下才使用 mmap 分配内存。 尽量只缓存临时使用的空闲小内存块,对大内存块或是长生命周期的大内存块在释放时都直接归还给操作系统。 对空闲的小内存块只会在 malloc 和 free 的时候进行合并,free 时空闲内存块可能放入 pool 中,不一定归还给操作系统。 收缩堆的条件是当前 free 的块大小加上前后能合并 chunk 的大小大于 64KB,并且堆顶的大小达到阈值,才有可能收缩堆,把堆最顶端的空闲内存返回给操作系统。 需要保持长期存储的程序不适合用 ptmalloc 来管理内存。 为了支持多线程,多个线程可以从同一个分配区(arena)中分配内存,ptmalloc假设线程

【Java自动内存管理机制】

别说谁变了你拦得住时间么 提交于 2019-12-18 05:56:09
Java内存区域   java虚拟机在执行java程序的过程中会把它所管理的内存划分成很多个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束而建立和销毁。Java虚拟机规范中把java虚拟机所管理的内存划分为以下几个区域。   一、程序计数器(Program Counter Register)   程序计数器是一块较小的内存空间,它的作用是当前所执行的字节码的行号指示器。它是线程私有的,即各个线程都有独立的程序计数器。   如果线程正在 执行一个java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是native方法,则这个计数器是空(undefined)。   此内存区域是唯一的一个不会抛出OutOfMemoryError异常的区域。   二、java虚拟机栈(Java Virtual Machine Stacks)   我们可能经常听到说java内存分为堆内存和栈内存,其实这个说法中的栈内存是指java虚拟机栈中的局部变量表部分。   Java虚拟机栈描述的是java方法执行的内存模型:每个方法被执行时都会同时创建一个栈帧(Stack Frame),用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直到执行完成的过程

JVM内存管理(二)

我们两清 提交于 2019-12-18 05:54:02
JVM 内存管理       JVM在执行java程序的过程中,会把内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁。 程序计数器    程序计数器:当前线程所执行字节码的行号指示器。    由于 JVM 的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器只会执行一条线程中的指令。为了线程切换后能够恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,各线程之间计数器互不影响,独立存储。   程序计数器:线程私有的内存。 Java 虚拟机栈    每个方法在执行的同时,都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。   每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。   局部变量所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。   Java 虚拟机栈,与程序计数器一样,是线程私有的,生命周期同线程相同。 本地方法栈   本地方法栈类似于虚拟机栈,区别在于:虚拟机栈为虚拟机执行 java 方法服务。   本地方法栈则为虚拟机执行 Native 方法服务。 Java 堆

JVM探索之内存管理(三)

人盡茶涼 提交于 2019-12-18 05:53:27
上节 我们介绍了JVM垃圾回收的原则,还有几个垃圾收集算法:标记-清除算法、复制算法、标记整理算法、分代收集算法;现在将要说HotSpt的垃圾收集器,这小节将只是理论。 Java虚拟机规范对垃圾收集器的具体实现并没有任何规定,所以不同厂商、不同版本的虚拟机提供的垃圾收集器会有很大的不同。下面所介绍的收集器只是HotSpt1.7的垃圾收集器。 HotSpot 堆的瓜分 HotSpt它把内存空间分为几个区域:新生代、老年代、永久代;上节中也说到了分代垃圾收集算法的主要思想按对象的生命周期来进行分组; 如上图JVM把堆划分为Young、Old、Perm三大区域,对应着不能年龄的对象;然后又把Young分为:Eden、Survivor From、Survivor To三小块;各个区域存放对象的区别如下: Young区 ,所有新创建的对象都存储在Eden区域中,当Eden满后将会触发minor GC把Eden中存活的对象复制到一个Survivor中,然后另一个Survivor存活对象也复制到这个中,始终保持一个Survivor区域为空的。 Old区 存放的是Survivor满后触发minor GC后依然存活的对象,如果从Eden复制到Survivor的对象存不了也可以直接存到Old区中等。Old区满了就会触发Full GC回收整个堆内存。 Perm区 存储类、方法、等的元信息

JVM探索之——内存管理(一)

我们两清 提交于 2019-12-18 05:53:11
本系列的 第一篇文章 ,预计本系列最后面会有两三个案例。 Java与C、C++不一样Java不需要Coder进行手动内存管理,而这一切都交给JVM进行自动内存管理,这从某种程度上来说也减轻了我们Coder不少的编码量,而我们是否还有必要了解JVM的内存管理机制呢,答案是否定的;因为Java也会和C、C++一样发生内存泄漏、内存溢出,尽管它发生这些事故会少很多,但一旦发生了而你又不了解他的内存管理机制这将是非常棘手的问题;还有个原因就是Java是运行在JVM上的,而不能JVM参数可能会影响到程序的执行性能,我们要想JVM在具体的应用中达到最优的性能那就必须了解JVM的内部机制;废话不多说现在开始JVM探索系列之——内存管理 根据《Java虚拟机规范》所规定的,Java虚拟机执行Java程序时它他管理的内存划分为几个区域,也就是运行时数据区(Run-Time Data Areas);这些区域的功能、生命周期各不相同,主要分为两大类:一种是随着JVM进程的启动而创建,随JVM进程消亡而销毁;一种是随着线程的创建而创建,随着线程的销毁而销毁,《Java虚拟机规范》规定的内存区域有如下图: 红色边框的两块区域为所有线程共享的(JVM进程的启动而创建、进程消亡而销毁) 其他三块区域为线程隔离的(线程的创建而创建,随着线程的销毁而销毁) 如图所示,运行时数据区(Run-time Areas)分为

JVM内存管理------GC简介

十年热恋 提交于 2019-12-18 03:36:54
为何要了解GC策略与原理? 原因在上一章其实已经有所触及,就是因为在平时的工作和研究当中,不可避免的会遇到内存溢出与内存泄露的问题。如果对GC策略与原理不了解的情况下碰到了前面所说的问题,很多时候会让人不知所措。 当我们了解了相关知识以后,虽然有时候依然不能很快的解决问题,但可以肯定的是,至少不会出现无计可施的情况。 GC策略解决了哪些问题? 既然是要进行自动GC,那必然会有相应的策略,而这些策略解决了哪些问题呢,粗略的来说,主要有以下几点。 1、哪些对象可以被回收。 2、何时回收这些对象。 3、采用什么样的方式回收。 GC策略采用的何种算法 有关上面所提到的三个问题,其实最主要的一个问题就是第一个,也就是哪些对象才是可以回收的。 有一种比较简单直观的办法,它的效率较高,被称作 引用计数算法 。但是这个算法有一个致命的缺陷,那就是对于循环引用的对象无法进行回收。想象一下,假设JVM采用这种GC策略,那么程序猿在编写的程序的时候,下面这样的代码就不要指望再出现了。 public class Object { Object field = null; public static void main(String[] args) { Thread thread = new Thread(new Runnable() { public void run() { Object objectA

C++内存管理(未完...)

安稳与你 提交于 2019-12-17 23:24:01
本文代码中出现的类 class Complex{ public: int num; Complex(int _num) : num(_num){} Complex(){} ~Complex(){} }; 四种常用内存申请方式 //--------四种内存申请方式---------- void* p1 = malloc(512); //申请512bytes free(p1); string* p2 = new string; //申请one object delete p2; void* p3 = ::operator new(512); //申请512bytes ::operator delete(p3); int* p4 = allocator<int>().allocate(5); //分配5个int //int* p4 = allocator<int>().allocate(5, (int*)0); //同上,但是(int*)0并没有必要 allocator<int>().deallocate(p4, 5); new、delete的解析 //---------------new的解析--------------------- //Complex* cp = new Complex(); //new的实现过程 Complex* cp; try{ void* men =

内存管理:页式虚拟内存管理

笑着哭i 提交于 2019-12-17 23:16:26
页式存储管理——虚拟内存——缺页中断,页面替换算法 开章明意 : 创建一个进程(创建进程是在磁盘中),进程以字节为单位编号,然后再进程分为许多页(每页4KB),内存中有对应的页框(设定同页)。通过页表(记录页和页框的对应关系),将最需要的页调入内存,其他页留在磁盘中。根据CPU的需要动态的更新页表,并调入调出页,实现对内存的充分利用。 本质就是:内存局部读入进程,其余的存储在磁盘中 内存不够用的问题—— 现阶段通常使用8G内存,但一个大型游戏就要10G+内存,如何解决? 虚拟内存 :给每个进程分配一个独立的地址空间(本质在磁盘上),每个进程独立的地址空间就叫虚拟内存。 虚拟内存中的页是连续的,但可以对应到内存中不连续的页框,这样就实现了对内存的充分利用。(不要求内存提供连续的存储空间) 当进程建立时, 数据储存于磁盘内的虚拟内存空间,也不需要为该进程去配置主内存空间,只有当该进程的页被调用的时候才会被加载到实际内存中。 操作系统为了管理内存,给每个进程都分配独立的地址空间,对32位的系统而言,这个空间的大小是4GB。这4GB并不是实际的物理内存,实际上并不存在,因此有虚拟内存这一名称。 建立映射关系: 页(page),页框(frame),页表 分为大小相等的多个块,称为页(Page).每个页都是虚拟内存中一段连续的地址(一般一页为4Kb),其中一部分对应物理内存上的一块(称为页框

Linux内存管理中的slab分配器

折月煮酒 提交于 2019-12-17 08:28:58
转载自: http://edsionte.com/techblog/archives/4019 Linux内核中基于伙伴算法实现的分区页框分配器适合大块内存的请求,它所分配的内存区是以页框为基本单位的。对于内核中小块连续内存的请求,比 如说几个字节或者几百个字节,如果依然分配一个页框来来满足该请求,那么这很明显就是一种浪费,即产生内部碎片(internal fragmentation) 为了解决小块内存的分配,Linux内核基于Solaris 2.4中的slab分配算法实现了自己的slab分配器。除此之外,slab分配器另一个主要功能是作为一个高速缓存,它用来存储内核中那些经常分配并释放的对象。 1.slab分配器的基本原理 slab分配器中用到了对象这个概念,所谓对象就是内核中的数据结构以及对该数据结构进行创建和撤销的操作。它的基本思想是将内核中经常使用的对象 放到高速缓存中,并且由系统保持为初始的可利用状态。比如进程描述符,内核中会频繁对此数据进行申请和释放。当一个新进程创建时,内核会直接从slab分 配器的高速缓存中获取一个已经初始化了的对象;当进程结束时,该结构所占的页框并不被释放,而是重新返回slab分配器中。如果没有基于对象的slab分 配器,内核将花费更多的时间去分配、初始化以及释放一个对象。 slab分配器有以下三个基本目标: 1