内存碎片

深入理解JVM Note

对着背影说爱祢 提交于 2020-02-02 13:28:40
第2章 Java内存区域与内存溢出异常 运行时数据区域 在虚拟机有栈、堆和方法区。 线程共享的:堆、方法区 不共享的:栈、程序计数器(代码执行的行号) 程序计数器(Program Counter Register): 一小块内存空间,单前线程所执行的字节码行号指示器。字节码解释器工作时,通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。 栈 通常我们定义一个对象的引用,还有就是函数调用的现场保存都使用内存中的栈空间。 栈是一种线形集合,其添加和删除元素的操作应在同一段完成。栈按照后进先出的方式进行处理。 存在栈中的数据可以共享。假设我们同时定义: int a = 3;  int b = 3; 编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找有没有字面值为3的地址,如果没找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处理int b = 3;在创建完b的引用变量后,由于在栈中已经有3这个字面值,便将b直接指向3的地址。这样,就出现了a与b同时均指向3的情况。 StackOverflowError 方法压入和弹出 连续 1.引用类型总是被分配到“堆”上。不论是成员变量还是局部 2.基础类型总是分配到它声明的地方:成员变量在堆内存里,局部变量在栈内存里。 比如

深入理解Java虚拟机01:

白昼怎懂夜的黑 提交于 2020-02-01 13:09:39
“串一串” Java 虚拟机的知识点 本文将按照 Content 中给出的四个部分加上 Java 的内存模型部分进行说明,首先先来说说 Java 的内存管理机制。 说说 Java 的内存管理机制 说说 Java 虚拟机程序执行 说说虚拟机性能监控及故障处理 说说 JIT 优化 说说 Java 的内存模型 (JMM) 说说 Java 的内存管理机制 和 C++ 相比,Java 的内存管理机制可谓是一大特色,程序员们不需要自己去写代码手动释放内存了,甚至你想自己干虚拟机都不给你干这个事情的机会(就是说,我们是没有办法自动触发 GC 的),虚拟机全权包办了 Java 的内存控制权力。这看起来挺美好的,不过也意味着,一旦虚拟机疏忽了(感觉不能赖虚拟机,毕竟虚拟机也不知道你能把程序写成那样啊……),发生了内存泄漏,问题都不好查,所以知道虚拟机到底是怎么管的内存就十分重要啦。 虚拟机对内存的管理,其实就是收拾那些存放我们不会再用的对象的内存,把它们清了拿来放新的对象。所以它首先需要研究下以下几个问题: 这堆报废了的对象到底被放哪了?(Java 堆和方法区) 5 个数据区域: 程序计数器 、 Java 虚拟机栈 、 本地方法栈 、 Java 堆 、 方法区 。 这堆放报废对象的地方会不会内存泄漏?或者换一个洋气点的叫法,会不会 OOM?( 每个区的 OOM ) 对象是咋被放到这些地方的?(

JVM高频面试题

风流意气都作罢 提交于 2020-01-31 23:56:56
1、 类的实例化顺序,比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,它们的执行顺序 先静态、先父后子。 先静态:父静态 > 子静态 优先级:父类 > 子类 静态代码块 > 非静态代码块 > 构造函数 一个类的实例化过程: 1、父类中的static代码块,当前类的static 2、顺序执行父类的普通代码块 3、父类的构造函数 4、子类普通代码块 5、子类(当前类)的构造函数,按顺序执行 6、子类方法的执行 2、 JVM内存分配 3、 Java 8的内存分代改进 从永久代到元空间,在小范围自动扩展永生代避免溢出 4、 JVM垃圾回收机制,何时触发MinorGC等操作  分代垃圾回收机制:不同的对象生命周期不同。把不同生命周期的对象放在不同代上,不同代上采用最合适它的垃圾回收方式进行回收。  JVM中共划分为三个代:年轻代、年老代和持久代。年轻代:存放所有新生成的对象;年老代:在年轻代中经历了N次垃圾回收仍然存活的对象,将被放到年老代中,故都是一些生命周期较长的对象;持久代:用于存放静态文件,如Java类、方法等。新生代的垃圾收集器命名为“minor gc”,老生代的GC命名为”Full GC 或者Major GC”.其中用System.gc()强制执行的是Full GC 判断对象是否需要回收的方法有两种: 1.引用计数 当某对象的引用数为0时,便可以进行垃圾收集。 2

c++堆,栈的存储方式及代码内存分配

天大地大妈咪最大 提交于 2020-01-31 22:32:25
使用对象指针 C语言中经典的指针在 C++ 中仍然广泛使用,尤其是指向对象的指针,没有它就不能实现某些功能。 Student stu ; Student * pStu = & stu ; 上面代码中创建的对象 stu 在栈上分配内存,需要使用&获取它的地址,例如: Student stu;Student *pStu = &stu; pStu 是一个指针,它指向 Student 类型的数据,也就是通过 Student 创建出来的对象。 当然,你也可以在堆上创建对象,这个时候就需要使用前面讲到的new关键字(C++ new和delete运算符简介),例如: Student *pStu = new Student; 在栈上创建出来的对象都有一个名字,比如 stu,使用指针指向它不是必须的。但是通过 new 创建出来的对象就不一样了,它在堆上分配内存,没有名字,只能得到一个指向它的指针,所以必须使用一个指针变量来接收这个指针,否则以后再也无法找到这个对象了,更没有办法使用它。也就是说,使用 new 在堆上创建出来的对象是匿名的,没法直接使用,必须要用一个指针指向它,再借助指针来访问它的成员变量或成员函数。 栈内存是程序自动管理的,不能使用 delete 删除在栈上创建的对象;堆内存由程序员管理,对象使用完毕后可以通过 delete 删除。在实际开发中,new 和 delete 往往成对出现

8.池化内存分配

我与影子孤独终老i 提交于 2020-01-31 19:56:11
netty内存管理思想 PooledByteBufAllocate PoolChunk Chunk初始化 PoolChunk分配内存 netty内存管理思想 java作为一门拥有GC机制的语言,长久以来它的使用者都不必手动管理内存,这比起c/c++是一个巨大的进步。但现在netty却反其道而行之,实现了一套不依赖GC而自行管理内存的机制。 那么netty为什么要这么做?众所周知netty是一个网络通信层框架,涉及到大量IO操作,对于此类操作,DirectByteBuffer无疑比起堆内存有更多性能上的优势。而与此同时,DirectByteBuffer也有自身的不足,那就是它的申请和释放成本更高。如果直接交给JVM管理,频繁的GC将使DirectByteBuffer的优势荡然无存。所以,对DirectByteBuffer进行池化管理,多次重用以减少申请、释放的想法就比较自然了。但是,不同于一般于我们常见的对象池、连接池等池化的案例,ByteBuffer有大小一说,且申请多大的内存进行管理也难以确定,如果大了会浪费,小了会导致频繁扩容和内存复制以及碎片化。因此netty需要在解决高效分配内存的同时又解决内存碎片化的问题,显然,它使用的算法就非常具有学习价值了。 由于内存管理有许多概念,有必要在前期做一些准备工作以帮助理解。 首先,考虑到netty是一个多线程环境

Linux 内存管理一

别来无恙 提交于 2020-01-31 11:03:20
疫情在家,整理下以前的学习笔记, 作为linux 三个最重要的部分之一(进程,io,内存),内存管理是非常重要的,是深入理解linux各个部分的基础,linux的内存管理与其他rtos的内存管理不一样,他是一个“富” os,也就是支持很多的应用同时跑,还需要支持应用之间的内存隔离。Linux 内存不仅仅用于内存,比如作为硬盘的补充,硬盘本身也可以作为内存来使用。 硬件原理和分页管理 只要我们打开了MMU之后,CPU只能看到虚拟地址,最终这个虚拟地址通过MMU根据页表查询到对应的硬件地址。比如要访问虚拟地址0x1234560,其中0x560 是页内偏移, 0x1234 是页号, 比如查到0x1234 对应的物理地址是1G,CPU访问0x1234560 的时候,实际访问的是1G+0x560 的地址。 物理地址是页表下面的一个数值,所以物理地址本质上是一个整数,而不是指针。地址是以*p访问到的,其实从linux中物理地址的数据类型也可以看出来 页表除了可以查虚拟地址对应的物理地址以外,还承担了一项非常重要的权限管理(RWX),RWX指读写执行权限,对linux安全非常重要,比如代码段映射为只读读加可执行,那么无论是应用还是内核里面的任何错误行为都不会改写代码段,只要一改写硬件就会发生page fault,软件的错误行为就会被硬件拦截,硬件里面还可以管理另外一个重要的权限

MYSQL配置参数优化详解

风流意气都作罢 提交于 2020-01-31 10:33:51
目录 1)连接请求的变量 1、max_connections 2、back_log 3、wait_timeout和interative_timeout 2)缓冲区变量 4、key_buffer_size 5、query_cache_size(查询缓存简称QC) 6、max_connect_errors: 7、sort_buffer_size: 8、max_allowed_packet=32M 9、join_buffer_size=2M 10、thread_cache_size=300 3)配置Innodb的几个变量 11、innodb_buffer_pool_size 12、innodb_flush_log_at_trx_commit 13、innodb_thread_concurrency=0 14、innodb_log_buffer_size 15、innodb_log_file_size=50M 16、innodb_log_files_in_group=3 17、read_buffer_size=1M 18、read_rnd_buffer_size=16M 19、bulk_insert_buffer_size=64M 20、binary log 参数汇总: MySQL参数优化对于不同的网站,及其在线量,访问量,帖子数量,网络情况,以及机器硬件配置都有关系,优化不可能一次性完成

.NET GC 精要(四)

若如初见. 提交于 2020-01-31 08:40:34
本文讲述了 .NET GC 的一些细节知识,内容大部分来自于书籍 Under the Hood of .NET Memory Management (注:本文假设你了解 .NET 的基础知识,譬如值类型,引用类型等) 进阶 之前 在讲述 GC 分代回收的时候,我们只是了解了一下 SOH(Small Object Heap) 相关的内存回收行为,实际上,在进行 Gen 2 GC(也称为 full GC)时, GC 流程同样会回收 LOH(Large Object Heap)的内存,只是在方式方法上, LOH 的内存回收和 SOH 的内存回收有很大不同. 首先, LOH 的内存分布比较"直白",并没有 SOH 中所谓的分代概念(Gen 0, Gen 1 和 Gen 2). 再者, 由于 LOH 存储的是大于等于 85000 字节的大对象,所以复制移动这些对象的成本很高,所以, LOH 也并不会进行内存压缩(SOH 对各个分代都会进行内存压缩). 在(大)对象的申请与释放(即 Gen 2 GC)过程中, LOH 会将各个可用的内存区域记录到一个被称为 Free Space Table 的表中: 在申请(大)对象时, .NET 会首先检查 Free Space Table,如果发现有足够的可用内存,则会将(大)对象分配到对应的可用内存区域中,并更新 Free Space Table

JVM内存管理和GC

匆匆过客 提交于 2020-01-30 18:55:46
JVM内存管理以及垃圾回收。 1、虚拟机垃圾收集所关注的区域 垃圾收集只关注 堆 和 方法区 两个运行时数据区域 其他区域程序计数器、虚拟机栈、本地方法栈这些都是随线程而生,随线程而亡的。 2、自动垃圾手机的前提是要知道哪些内存可以被释放和回收。 对于实例收集监测主要有两种基本算法, 引用计数 和 可达性分析 1、引用计数算法 为对象添加一个引用计数器,没被引用一次计数器加一,引用被释放则计数器减一。当计数器为0的时候即表示对象可被回收。 缺点 引用计数存在一个基本难题,也就是很难处理循环引用的问题 2、可达性算法。 (1) 将对象及其引用关系看做一个图,选定活动的对象作为GC Roots,然后跟踪引用链条,如果一个对象和GC Roots之间不可达,也就是不存在引用链条,那么就可认为这个对象是可回收对象。 (2) 那么哪些对象可以被选 做为GC Roots呢 ? 1、JVM会把虚拟机栈中引用的对象。 2、本地方法栈中引用的对象。 3、静态属性引用的对象。 4、常量。 3、常见的垃圾手机算法。 (1)标记-清楚(Mark-Sweep)算法。 这个算法分两步走“标记”和“清除”,标记出所有要回收的对象,然后进行清除。这是最基础的收集算法,其他收集算法都是基于他再改进的。 缺点 标记和清除过程效率有限,另外就是不可避免出现碎片化问题。 (2)复制算法 背景 为了解决方法(1)的效率问题。

C/C++内存分配问题

孤街醉人 提交于 2020-01-30 11:08:04
一个C/C++程序经过编译后,占用的内存主要分为以下5个部分 (地址由高到低) 1、栈区(stack) — 运行时分配 2、堆区(heap) — 运行时分配 3、全局区(静态区static) — 保存在 ELF 可重定位目标文件中 (1)已初始化的全局(静态)变量: .data段 (2)未初始化的全局(静态)变量: .bss段 4、文字常量区 — 保存在 ELF 可重定位目标文件中的 .rodata 段 5、程序代码区 — 保存在 ELF 可重定位目标文件中的 .text 段 栈区 :由编译器自动分配和释放。 栈区存放的内容: (1)函数的返回地址和函数的参数。 (2)函数在调用前后需要保持、不变的寄存器。 (3)函数的非静态(static)局部变量以及编译器自动生成的其他临时变量。 在C/C++程序中:主函数,中断服务函数,以及多任务系统(RTOS)中的任务函数 ,或者linux系统中的进程,它们的执行都需要各自运行栈的支持。 堆区 :由程序员调用 malloc 函数主动申请,需要释放时调用 free 函数释放。 若申请了堆区的内存之后忘记释放,很容易造成内存泄漏。频繁地申请和释放堆区内存会产生堆区碎片。 全局区(静态区static) :存放程序的数据(程序 = 指令 + 数据)。 文字常量区 :存放程序的数据(程序 = 指令 + 数据)。 程序代码区 :存放程序的指令(程序 =