内存管理

JVM内存管理基本知识

不问归期 提交于 2020-03-08 04:30:34
这篇本来是想好好写的,今天看了一天了的,可是,组会好像有种要悲剧的感觉啊。。暴风雨前的宁静,尽量记录一些吧。 上周把爬虫代码优化后,就哈皮哈皮的和未优化的版本一起跑了。起初,由于未优化的版本已经run了几天了,内存占用在200M多,而发现优化后的内存占用只有40M,所以很开心。但是不久就发现,优化后的版本,内存占用也会慢慢增加,大有一种“老娘给你分多少,你就要用多少”的赶脚。 用jprofiler监控,自己开发的类的对象数量都比较正常,所以决定学习一下JVM内存管理相关的东西。 JVM主要管理两种类型的内存:堆(Heap)和非堆。 按照官方的说法:“Java虚拟机具有一个堆, 堆 是 运行时 数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。” “在JVM中堆之外的内存称为 非堆 内存(Non-heap memory)”。简单来说堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给自己用的,所以方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中。 堆内存分配 JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到

Linux虚拟内存相关知识

梦想与她 提交于 2020-03-07 14:15:36
Linux 的虚拟内存管理有几个关键概念: 1、每个进程都有独立的虚拟地址空间,进程访问的虚拟地址并不是真正的物理地址; 2、虚拟地址可通过每个进程上的页表(在每个进程的内核虚拟地址空间)与物理地址进行映射,获得真正物理地址; 3、如果虚拟地址对应物理地址不在物理内存中,则产生缺页中断,真正分配物理地址,同时更新进程的页表;如果此时物理内存已耗尽,则根据内存替换算法淘汰部分页面至物理磁盘中。 Linux 虚拟地址空间如何分布? Linux 使用虚拟地址空间,大大增加了进程的寻址空间, 虚拟地址空间内由低地址到高地址分别为: 1、只读段:该部分空间只能读,不可写;(包括:代码段、rodata 段(C常量字符串和#define定义的常量) ) 2、数据段:保存全局变量、静态变量的空间; 3、堆 :就是平时所说的动态内存, malloc/new 大部分都来源于此。其中堆顶的位置可通过函数 brk 和 sbrk 进行动态调整。 4、文件映射区域:如动态库、共享内存等映射物理空间的内存,一般是 mmap 函数所分配的虚拟地址空间。 5、栈:用于维护函数调用的上下文空间,一般为 8M ,可通过 ulimit –s 查看。 6、内核虚拟空间:用户代码不可见的内存区域,由内核管理(页表就存放在内核虚拟空间)。 32 位系统有4G 的地址空间:: 其中 0x08048000~0xbfffffff

Linux内存管理专题

北城以北 提交于 2020-03-07 14:15:08
专题: Linux内存管理专题 关键词: malloc、brk、VMA、VM_LOCK、normal page、special page 。 每章问答: malloc()函数是C函数库封装的一个核心函数,对应的系统调用是brk()。 1. brk实现 要了解brk的实现首先需要知道进程用户空间的划分,以及struct mm_struct结构体中代码段、数据段、堆相关参数。 然后brk也是基于VMA,找到合适的虚拟地址空间,创建新的VMA并插入VMA红黑树和链表中。 首先看看mm_struct中代码段、数据段相关参数,和 Linux内存管理框架图 结合看。 由于栈向低地址空间增长,堆向高地址空间增长,所以栈的起始地址start_stack和堆的结束地址brk会改变。在栈和堆之间是 struct mm_struct { ... unsigned long start_code, end_code, start_data, end_data;-----代码段从start_code到end_code;数据段从start_code到end_code。 unsigned long start_brk, brk, start_stack;--------------------堆从start_brk开始,brk表示堆的结束地址;栈从start_stack开始。 unsigned long arg

Linux的Application 内存模型---

守給你的承諾、 提交于 2020-03-07 14:08:21
Linux的内存模型,一般为: 现在的每个进程使用了全部4G线性空间。在加载程序时内核把程序加载到线性地址0x08048000开始的位置。这个位置当然>128MB。2G开始是共享库,3G开始是内核。 地址------------------------作用--------------------------说明 >=0xc0000000---------内核虚拟存储器-------------用户代码不可见区域 < 0xc0000000----------Stack(用户栈)------------ESP指向栈顶,向下增长 -------------------------------------------------空闲内存 >=0x40000000---------文件映射区------------------mmap的空间 < 0x40000000-------------------------------------空闲内存 ---------------------Heap(运行时堆)--------------通过brk/sbrk系统调用扩大堆,向上增长。 ---------------------.data、.bss(读写段)---------从可执行文件中加载 >=0x08048000---------.init、.text、.rodata------

slab、slub内存管理与泄漏分析

☆樱花仙子☆ 提交于 2020-03-06 15:51:49
经典博客 类型 文章 slab、slub的关系 SLUB和SLAB的区别 系统性介绍kernel内存泄漏检测 Linux内存管理 (22)内存检测技术 、 Linux内存使用情况以及内存泄露分析之工具与方法 drop_cache应用 liunx的Slab占用比较高的问题 slub、slab内存泄漏诊断有区别 https://blog.csdn.net/dolp怎样诊断SLAB泄露问题 判断slub、slab是否内存泄漏 linux通过meminfo 与 slab 定位内存泄漏 实例 认识Kernel 内存泄漏 、 slub泄露分析 工具介绍与使用 kmemleak的使用 触发slab回收 博文: https://www.iteye.com/blog/fengbin2005-2218722 上文排查到Linux系统中有大量的dentry_cache占用内存,为什么会有如此多的dentry_cache呢? 首先,弄清楚dentry_cache的概念及作用:目录项高速缓存,是Linux为了提高目录项对象的处理效率而设计的;它记录了目录项到inode的映射关系。因此,当应用程序发起stat系统调用时,就会创建对应的dentry_cache项(更进一步,如果每次stat的文件都是不存在的文件,那么总是会有大量新的dentry_cache项被创建)。 当前服务器是storm集群的节点

又能扯皮了!没内存了还能看片?

拥有回忆 提交于 2020-03-06 15:35:58
虚拟内存 尽管基址寄存器和变址寄存器用来创建地址空间的抽象,但是这有一个其他的问题需要解决: 管理软件的膨胀(managing bloatware) 。虽然内存的大小增长迅速,但是软件的大小增长的要比内存还要快。在 1980 年的时候,许多大学用一台 4 MB 的 VAX 计算机运行分时操作系统,供十几个用户同时运行。现在微软公司推荐的 64 位 Windows 8 系统至少需要 2 GB 内存,而许多多媒体的潮流则进一步推动了对内存的需求。 这一发展的结果是,需要运行的程序往往大到内存无法容纳,而且必然需要系统能够支持多个程序同时运行,即使内存可以满足其中单独一个程序的需求,但是从总体上来看内存仍然满足不了日益增长的软件的需求(感觉和xxx和xxx 的矛盾很相似)。而交换技术并不是一个很有效的方案,在一些中小应用程序尚可使用交换,如果应用程序过大,难道还要每次交换几 GB 的内存?这显然是不合适的,一个典型的 SATA 磁盘的峰值传输速度高达几百兆/秒,这意味着需要好几秒才能换出或者换入一个 1 GB 的程序。 SATA(Serial ATA)硬盘,又称串口硬盘,是未来 PC 机硬盘的趋势,已基本取代了传统的 PATA 硬盘。 那么还有没有一种有效的方式来应对呢?有,那就是使用 虚拟内存(virtual memory) ,虚拟内存的基本思想是,每个程序都有自己的地址空间

操作系统内存管理中的分段、分页简单理解

懵懂的女人 提交于 2020-03-06 13:36:37
作者:codinghuang 链接:https://www.zhihu.com/question/50796850/answer/522734117 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 要理解分段和分页,那么得理解为什么会出现分段和分页的技术 首先,这两个技术都是 为了利用和管理好计算机的资源--内存 。 在分段这个技术还没有出现之前,程序运行是需要从内存中分配出足够多的 连续的 内存,然后把 整个 程序装载进去。举个例子,某个程序大小是10M,然后,就需要有 连续的 10M内存空间才能把这个程序装载到内存里面。如果无法找到连续的10M内存,就无法把这个程序装载进内存里面,程序也就无法得到运行。 上面这种直接把整个程序装载进内存的方式是有一定的问题的。例如: 1、地址空间不隔离 如何理解地址空间不隔离? 举个例子,假设我有两个程序,一个是程序A,一个是程序B。程序A在内存中的地址 假设 是0x00000000~0x00000099,程序B在内存中的地址 假设 是0x00000100~x00000199。那么假设你在程序A中,本来想操作地址0x00000050,不小心 手残 操作了地址0x00000150,那么,不好的事情或许会发生。你影响了程序A也就罢了,你把程序B也搞了一顿。 2、程序运行时候的地址不确定

C++内存管理

喜欢而已 提交于 2020-03-05 21:19:36
动态内存 1、new和malloc的区别。(1) • new是运算符,malloc()是一个库函数; • new会调用构造函数,malloc不会; • new返回指定类型指针,malloc返回void*指针,需要强制类型转换; • new会自动计算需分配的空间,malloc不行; • new可以被重载,malloc不能。 2、智能指针(1) 智能定义在<memory>头文件中的std命名空间中定义的,目的是更容易(同时也更安全)地使用动态内存,对RAII技术至关重要。 C++标准中引入命名空间的概念,是为了解决不同模块或者函数库中相同标识符冲突的问题。有了命名空间的概念, 标识符就被限制在特定的范围(函数)内 ,不会引起命名冲突。最典型的例子就是 std命名空间 , C++标准库中所有标识符都包含在该命名空间中 。 RAII是C++的发明者Bjarne Stroustrup提出的概念,RAII全称是“Resource Acquisition is Initialization”,直译过来是“ 资源获取即初始化 ”,也就是说在构造函数中申请分配资源,在析构函数中释放资源。因为C++的语言机制保证了,当一个对象创建的时候,自动调用构造函数,当对象超出作用域的时候会自动调用析构函数。所以, 在RAII的指导下,我们应该使用类来管理资源,将资源和对象的生命周期绑定。 智能指针(std:

虚拟内存管理

独自空忆成欢 提交于 2020-03-05 08:54:54
1、什么是虚拟内存 虚拟内存是计算机系统内存管理的一种技术。它使的应用程序认为他拥有连续的可用内存( 一个连续完整的地址空间 ),而实际上,他通常是被分割成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。 注意:虚拟内存不只是“用磁盘空间来扩展物理内存”的意思--这只是扩充内存级别以使其包含磁盘驱动器而已,把内存扩展到磁盘只是使用虚拟内存技术的一个结果,他的作用可以通过覆盖或者把处于不活动状态的程序以及他们的数据交换到磁盘上等方式实现。 2、为什么会有虚拟内存 许多年以前,当人们还在使用DOS或更古老的操作系统的时候,计算机内存还非常小,一般都是以K为单位进行计算的,相应的,当时的程序规模也不大,所以内存容量虽然小,但还是可以容纳当时的程序。但随着图像界面的想起还有用户需求的不断增大,应用程序的规模也随之膨胀起来。终于一个难题出现在程序员面前,那就是应用程序太大以至于内存容不下该程序,通常解决的办法是把程序分割成许多覆盖快的片段。覆盖块0首先运行,结束时他将调用另一个覆盖块。虽然覆盖块的交换是由os完成的,但是必须先有程序员吧程序先进行分割,这是一个费时费力的工作,而且相当枯燥。虚拟存储器就应运而生。 3、物理地址、虚拟地址、逻辑地址区别 32位系统的地址总线是32位的, 64位 CPU是指 CPU 内部的通用寄存器的宽度为 64 比特

MMU内存管理单元

女生的网名这么多〃 提交于 2020-03-03 20:52:13
arm-linux学习-(MMU内存管理单元) 什么是MMU MMU(Memory Management Unit)主要用来管理虚拟存储器、物理存储器的控制线路,同时也负责 虚拟地址映射为物理地址 ,以及提供硬件机制的内存访问授权、多任务多进程操作系统。(来自百度百科, 对其几个点不熟悉,因此可以只考虑加粗部分 ) 发展历史 注意:学习一个知识点,很重要的一步是了解其 为什么而存在?它的存在是为了解决什么问题? 然后,在学习的过程中带着这些问题去理解、去思考。 在许多年以前,还是使用DOS或一些古老的操作系统时,内存很小,同时,应用程序也很小,将程序存储在内存中基本能够满足需要。随着科技的发展,图形界面及一些其他更复杂的应用出现,内存已经无法存储这些应用程序了,通常的解决办法是将程序分割成很多个 覆盖块 ,覆盖块0最先运行,运行结束之后,就调用另一个覆盖块,虽然这些操作由OS来完成,但是,需要程序员对程序进行分割,这非常不高效;因此,人们想出了一个 虚拟存储器(virtual memory) 的方法。虚拟存储器的基本思想是:程序、数据、堆栈的总大小可以超过内存空间的大小,操作系统将当前运行的部分保存在内存中,未使用的部分保存在磁盘中。比如一个16MB的程序和一个内存只有4MB的机器,操作系统通过选择可以决定哪部分4MB的程序内容保存在内存中,并在需要时,在内存与磁盘中交换程序代码