内存又叫主存,是CPU与其他设备沟通的桥梁,主要用来临时存放数据,配合CPU工作,协调CPU的处理速度
内存的组成:内存地址+存储单元
两种不同的数据结构
一种经过排序的树型数据结构
存放程序的对象
数组、列表:数据是有顺序的,从左到右,从0开始。如果要在列表中,插入一个数据,那么在插入位置之后的数据,都需要移动,删除列表中间某个数据,在位置之后的数据,也都要移动。
链表也是一种数组,它的每个数据存储的都是数据值+下一个元素的地址。
如果要在链表中,插入一个数据。插入位置「前一个元素」中的「下一个元素的地址」需要指向插入的数据的地址,「待插入的元素」记录「下一个元素的地址」。
查找一个数据时,需要从头开始读取数据,一个一个的比对,直到找到需要的数据才停止。这个过程会有大量的IO,所以读取数据速度并不快。
建立在链表的基础上的一种数据结构
二叉树左边存储的是小于自身数据,右边是存储大于自身数据
插入数据:因为是链表,插入速度也比较快
读取数据:因为数据已经做了二分,查找链路变短,IO就减少了,读取速度也变快
二叉树的不足:随着存储的数据量增大,二叉树会越来越大,那要查找某个数据的IO次数,也会非常多
不是一个简单的平衡二叉树,是一个立体的平衡二叉树
B树和平衡二叉树稍有不同的是B树属于多叉树又名平衡多路查找树(查找路径不只两个),数据库索引技术里大量使用者B树和B+树的数据结构
LIFO「Last In First Out」后进先出
FIFO「First In First Out」先进先出
一个程序运行起来,需要分配一块内存空间,无异常时,就在分配的空间中弹性伸缩存储
这个存储空间至少包含一块栈区,一块堆区,还会包括其他
程序计数器、java虚拟机栈、本地方法栈、方法区、堆内存
OOM会导致整个内存条空间全被使用吗?不会!只会消耗该程序申请的空间,不会消耗内存条全部空间
GC资源回收
需要有GC,但是频率要合理,不能过高
垃圾回收算法:新生代-复制算法「清理Eden,将存活的复制到Survivor」,年老代-标记整理算法「先标记,再整理」
只有在讲「堆」的时候,才会说资源回收。本地方法栈、程序计数器、虚拟机栈这些是不需要进行垃圾回收的
内存空间中垃圾回收的工作由垃圾回收器「Garbage Collecot,GC」完成。它的核心思想是:对虚拟机可用内存空间,即堆空间中的对象进行识别,如果对象正在被引用,那么称其为存活对象,反之,如果对象不再被引用,则为垃圾对象,可以回收其占据的空间,用于再分配。
-Xms
:初始堆大小
-Xmx
:最大堆空间
-Xmn
:设置新生代大小
-XX:SurivivorRatio
:新生代eden空间,from空间,to空间的比例关系
-XX:PermSize
:方法区初始大小
-XX:MaxPermSize
:方法区最大值
-XX:MetaspaceSize
:元空间GC阈值
-XX:MaxMetaspaceSize
:最大元空间大小
-Xss
:栈大小
-XX:MaxDirectMemorySize
:直接内存大小,默认为最大堆空间
root@zx:~# free -h
total used free shared buff/cache available
Mem: 3.8Gi 414Mi 293Mi 2.0Mi 3.2Gi 3.2Gi
Swap: 0B 0B 0B
Mem:物理内存
Swap:交换分区
一种虚拟内存,由磁盘虚拟化而来,存在于内存和磁盘之间,因为磁盘和内存之间速度存在差异
top - 14:51:35 up 169 days, 4:55, 1 user, load average: 0.01, 0.02, 0.00
Tasks: 108 total, 1 running, 107 sleeping, 0 stopped, 0 zombie
%Cpu(s): 1.2 us, 0.5 sy, 0.0 ni, 98.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 3936.1 total, 294.0 free, 414.6 used, 3227.6 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 3266.4 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
479183 root 10 -10 128.7m 37.5m 14.5m S 2.3 1.0 487:05.64 AliYunDun
672280 root 20 0 59.3m 53.2m 5.9m S 1.0 1.4 139:43.55 gunicorn
479138 root 10 -10 21.8m 5.7m 4.9m S 0.3 0.1 27:41.60 AliYunDunUpdate
VIRT 虚拟内存使用量 = Swap + RES
RES 物理内存使用量+未换出的虚拟内存大小 = CODE + DATA
SHR 共享内存使用量
Swap 虚拟内存中被换出的大小
CODE 代码占用的物理内存大小
DATA 代码之外的部分占用的物理内存大小
%MEM 使用的物理内存占总内存的比率
命令:jmap [options] pid
-dump
:生成java堆栈的快照信息
-heap
:显示java堆详细信息,使用那种回收机制,参数配置,分代情况
-histo
:显示堆中对象统计信息,包括类,实例数量
jmap -F -dump:format=b,file=jvmpertest110901.bin 3636
format=b 格式为二进制
file 输出到什么文件,文件格式.bin
3636 进程pid
这个命令,执行时间很长,生成的文件也很大
阿里巴巴开源的java诊断工具,实现了jvm自带的几乎所有诊断功能
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
jvm的启动参数中加入
-XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimestamps -XX:+PrintGCApplicationsStopedTime
启动后输出:GC概要信息,详细信息,gc时间,gc造成的应用暂停时间
jdk自带的内存分析工具,有图形界面,可以查看jvm内存信息,线程信息,类加载信息,MBean信息
jconsole.sh pid
jdk自带的分析gc工具,参数很多
jstat -gcutil pid 10000 间隔10000毫秒显示一次gc信息