08月01, 2018

JVM-堆内存-进程内存研究

JVM-堆内存-进程内存研究

  • 1 linux进程内存介绍top
  • 2 jvm堆内存介绍xmx
  • 3 进程内存与jvm内存的关系
  • 4 jvm线程与linux线程关系,以及内存占用情况
  • 5 为什么进程内存远远大于xmx内存

1、linux进程内存介绍top

1.1 介绍

实时动态的查看系统的整体运行情况,是一个综合了多方信息监测系统性能和运行信息的工具。通过top命令所提供的互动式界面,用热键可以管理。

1.2 语法

top -hv | -abcHimMsS -d delay -n iterations -p pid [, pid ...]

1.3 详解

选项

-b:以批处理模式操作;
-c:显示完整的治命令;
-d:屏幕刷新间隔时间;
-I:忽略失效过程;
-s:保密模式;
-S:积累模式;
-i<时间>:设置间隔时间;
-u<用户名>:指定用户名;
-p<进程号>:指定进程;
-n<次数>:循环显示的次数。

交互式命令

h:显示帮助画面,给出一些简短的命令总结说明;
k:终止一个进程;
i:忽略闲置和僵死进程,这是一个开关式命令;
q:退出程序;
r:重新安排一个进程的优先级别;
S:切换到累计模式;
s:改变两次刷新之间的延迟时间(单位为s),如果有小数,就换算成ms。输入0值则系统将不断刷新,默认值是5s;
f或者F:从当前显示中添加或者删除项目;
o或者O:改变显示项目的顺序;
l:切换显示平均负载和启动时间信息;
m:切换显示内存信息;
t:切换显示进程和CPU状态信息;
c:切换显示命令名称和完整命令行;
M:根据驻留内存大小进行排序;
P:根据CPU使用百分比大小进行排序;
T:根据时间/累计时间进行排序;
w:将当前设置写入~/.toprc文件中。

1.4 例子

top

top - 17:43:57 up 524 days, 16:06,  1 user,  load average: 0.03, 0.06, 0.02
Tasks: 158 total,   1 running, 157 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.2%us,  0.2%sy,  0.0%ni, 99.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   5993932k total,  5867592k used,   126340k free,   237900k buffers
Swap:  8191992k total,   857960k used,  7334032k free,  1212888k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND    
24060 zabbix    20   0 81824  904  764 S  0.7  0.0  36:30.09 zabbix_agentd                                                                                                                           
30446 newsettl  20   0 3311m 670m 4728 S  0.7 11.5 370:57.53 java                                                                                                                                    
   21 root      20   0     0    0    0 S  0.3  0.0  53:09.62 events/2                                                                                                                                
 4985 newsettl  20   0 15036 1260  932 R  0.3  0.0   0:00.08 top                                                                                                                                     
 5752 newsettl  20   0 7012m 1.6g 5592 S  0.3 27.9 137:18.72 java                                                                                                                                    
15792 root      20   0  305m 1136  972 S  0.3  0.0 185:49.83 unifyTlogc                                                                                                                              
20868 newsettl  20   0 3692m 474m  10m S  0.3  8.1  21:16.14 java                                                                                                                                    
27041 newsettl  20   0 3548m 591m  10m S  0.3 10.1   1:02.77 java                                                                                                                                    
    1 root      20   0 19364  776  556 S  0.0  0.0   0:20.50 init      

解释:

top - 09:44:56[当前系统时间],
16 days[系统已经运行了16天],
1 user[个用户当前登录],
load average: 9.59, 4.75, 1.92[系统负载,即任务队列的平均长度]
Tasks: 145 total[总进程数],
2 running[正在运行的进程数],
143 sleeping[睡眠的进程数],
0 stopped[停止的进程数],
0 zombie[冻结进程数],
Cpu(s): 99.8%us[用户空间占用CPU百分比],
0.1%sy[内核空间占用CPU百分比],
0.0%ni[用户进程空间内改变过优先级的进程占用CPU百分比],
0.2%id[空闲CPU百分比], 0.0%wa[等待输入输出的CPU时间百分比],
0.0%hi[],
0.0%st[],
Mem: 4147888k total[物理内存总量],
2493092k used[使用的物理内存总量],
1654796k free[空闲内存总量],
158188k buffers[用作内核缓存的内存量]
Swap:  5144568k total[交换区总量],
56k used[使用的交换区总量],
5144512k free[空闲交换区总量],
2013180k cached[缓冲的交换区总量],

2 jvm堆内存介绍xmx

2.1 内存区域图

jvm内存回收示意图

jstat -gc 27041 200 10

 S0C    S1C    S0U    S1U      EC       EU        OC         OU       PC     PU    YGC     YGCT    FGC    FGCT     GCT   
48384.0 48384.0  0.0    0.0   236608.0 145152.6  349568.0   66524.3   170112.0 82163.5     12    0.701   2      0.475    1.176
48384.0 48384.0  0.0    0.0   236608.0 145152.6  349568.0   66524.3   170112.0 82163.5     12    0.701   2      0.475    1.176
48384.0 48384.0  0.0    0.0   236608.0 145152.6  349568.0   66524.3   170112.0 82163.5     12    0.701   2      0.475    1.176
48384.0 48384.0  0.0    0.0   236608.0 145152.6  349568.0   66524.3   170112.0 82163.5     12    0.701   2      0.475    1.176
48384.0 48384.0  0.0    0.0   236608.0 145152.6  349568.0   66524.3   170112.0 82163.5     12    0.701   2      0.475    1.176
48384.0 48384.0  0.0    0.0   236608.0 145152.6  349568.0   66524.3   170112.0 82163.5     12    0.701   2      0.475    1.176
48384.0 48384.0  0.0    0.0   236608.0 145152.7  349568.0   66524.3   170112.0 82163.5     12    0.701   2      0.475    1.176
48384.0 48384.0  0.0    0.0   236608.0 145152.7  349568.0   66524.3   170112.0 82163.5     12    0.701   2      0.475    1.176
48384.0 48384.0  0.0    0.0   236608.0 145152.7  349568.0   66524.3   170112.0 82163.5     12    0.701   2      0.475    1.176
48384.0 48384.0  0.0    0.0   236608.0 145152.7  349568.0   66524.3   170112.0 82163.5     12    0.701   2      0.475    1.176

2.2 内存结构

现在来解释各列含义:

    S0C、S1C、S0U、S1U:Survivor 0/1区容量(Capacity)和使用量(Used)
    EC、EU:Eden区容量和使用量
    OC、OU:年老代容量和使用量
    PC、PU:永久代容量和使用量
    YGC、YGT:年轻代GC次数和GC耗时
    FGC、FGCT:Full GC次数和Full GC耗时
    GCT:GC总耗时

总内存 = 永久代  + 堆内存
堆内存 = 老年代  + 年轻代 + (S0S1)
年轻代 = Eden + (S0S1)

New Generation = Eden + 1 Servivor
NewRatio = 2  tenured:(Eden + From + To) = 2:1
SurvivorRatio = 8  Eden:From:To = 8:1:1

JVM内存区域总体分两类,heap区 和 非heap 区(本地内存) 。

  • heap区: 堆区分为Young Gen(新生代),Tenured Gen(老年代-养老区)。其中新生代又分为Eden Space(伊甸园)、Survivor Space(幸存者区)。
  • 非heap区: Code Cache(代码缓存区)、Perm Gen(永久代)、Jvm Stack(java虚拟机栈)、Local Method Statck(本地方法栈)。

参考链接:https://blog.csdn.net/wwd0501/article/details/79410247

3、进程内存与jvm内存的关系

参考链接:https://www.cnblogs.com/springsource/p/6097736.html 参考链接:https://blog.csdn.net/wwd0501/article/details/79410247

###3.1 研究实例

运行个程序,sleep hold住,通过byte数组设置内存

package org.hjb.test; 
public class TestOnly {

    public static void main(String[] args) { 

        System.out.println("sleep .."); 
        try { 
            byte[] buf = new byte[1024 * 1024 * 1024];
            Thread.sleep(10000000); 
        } catch (InterruptedException e) { 
            e.printStackTrace(); 
        } 
    } 
}

观察内存
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 27445 root 20 0 3345308 1.034g 13688 S 0.0 26.8 0:00.89 java

观察得出 Java程序中实际使用内存才会用到内存,此时查看Java内存,只有当前用到了内存才会进RES. java进程内存 = JVM进程内存 + heap内存 + 永久代内存 + 本地方法栈内存 + 线程栈内存 + 对外内存 + socket缓冲区内存

linux进程内存与jvm内存关系 RES = JAVA正在存活的内存对象大小 + 未回收的对象大小 + 其它 VIART = JAVA中申请的内存大小,即 -Xmx -Xms + 其它 其它 = 永久代内存 + 本地方法栈内存 + 线程栈内存 + 堆外内存 + socket缓冲区内存

DirectByteBuffer 这是我们查这个问题首先要想到的一个地方,是否是因为什么地方不断创建DirectByteBuffer对象,但是由于没有被回收导致了内存泄露呢,之前有篇文章已经详细介绍了这种特殊对象 JVM源码分析之堆外内存完全解读 ,对阿里内部的童鞋,可以直接使用zprofiler的heap视图里的堆外内存分析功能拿到统计结果,知道后台到底绑定了多少堆外内存还没有被回收。

附录:

  • VIRT: virtual memory usage 1、进程“需要的”虚拟内存大小,包括进程使用的库、代码、数据等 2、假如进程申请100m的内存,但实际只使用了10m,那么它会增长100m,而不是实际的使用量

  • RES: resident memory usage 常驻内存 1、进程当前使用的内存大小,但不包括swap out 2、包含其他进程的共享 3、如果申请100m的内存,实际使用10m,它只增长10m,与VIRT相反 4、关于库占用内存的情况,它只统计加载的库文件所占内存大小

  • SHR: shared memory 1、除了自身进程的共享内存,也包括其他进程的共享内存 2、虽然进程只使用了几个共享库的函数,但它包含了整个共享库的大小 3、计算某个进程所占的物理内存大小公式:RES – SHR 4、swap out后,它将会降下来DATA1、数据占用的内存。如果top没有显示,按f键可以显示出来。 2、真正的该程序要求的数据空间,是真正在运行中要使用的。

3.2 物理内存远大于Xmx内存的问题分析

转载链接:https://www.cnblogs.com/duanxz/p/6148534.html

遗留问题:

堆外内存DirectByteBuffer:http://lovestblog.cn/blog/2015/05/12/direct-buffer/

system.gc:http://lovestblog.cn/blog/2015/05/07/system-gc/

String.intern:JVM源码分析之String.intern()导致的YGC不断变长

OutOfMemoryError:

JVM源码分析之String.intern()导致的YGC不断变长

JVM源码分析之不保证顺序的Class.getMethods

JVM源码分析之Metaspace解密

JVM源码分析之临门一脚的OutOfMemoryError完全解读

JVM源码分析之Jstat工具原理完全解读

JVM源码分析之不可控的堆外内存

YGC前后新生代变大?

JVM源码分析之JDK8下的僵尸(无法回收)类加载器

JVM源码分析之栈溢出完全解读

JDK8在泛型类型推导上的变化

不可逆的类初始化过程

如何定位消耗CPU最多的线程

JVM源码分析之Object.wait/notify(All)完全解读

JVM源码分析之自定义类加载器如何拉长YGC

消失的死锁

JVM源码分析之javaagent原理完全解读

进程物理内存远大于Xmx的问题分析

JVM源码分析之FinalReference完全解读

JVM源码分析之堆外内存完全解读

JVM源码分析之SystemGC完全解读

JVM Bug:多个线程持有一把锁?

从日志上理解JAVA调试机制

JDK的sql设计不合理导致的驱动类初始化死锁问题

通过HSDB来了解String值的真身在哪里

JVM Attach机制实现

从tcp原理角度理解Broken pipe和Connection reset by peer的区别

本文链接:http://www.zhaoxudong.cn/post/javavm.html

-- EOF --

Comments

请在后台配置评论类型和相关的值。