linux分析heap命令,关于linux下内存问题排查的工具

对最近linux下排查java内存相关问题的命令做个小的总结

linux系列

top

top -p PID

pid为12415进程的资源消耗情况。这里是以进程为单位。

b2d56579772c

top -Hp PID

b2d56579772c

这里是以线程为单位。其中RES看到没有线程占用的内存都是3.3g,是因为JVM内存区域中大部分都是线程共享的。

同时也可以通过shift+h在-p视图下切换至线程视图(set threads On),如下图:

b2d56579772c

说明:top命令的TIME/TIME+是指的进程/线程所使用的CPU时间,不是进程/线程启动到现在的时间,因此,如果一个进程/线程使用的cpu很少,那即使这个进程/线程已经存在N长时间,TIME/TIME+也是很小的数值。

/proc/$pid/status

[#]$ cat /proc/12415/status

Name: java

State: S (sleeping)

Tgid: 12415

Pid: 12415

PPid: 1

TracerPid: 0

Uid: 502 502 502 502

Gid: 501 501 501 501

Utrace: 0

FDSize: 512

Groups: 501

VmPeak: 6734784 kB

VmSize: 6732236 kB

VmLck: 0 kB

VmHWM: 3476100 kB

VmRSS: 3473752 kB

VmData: 6560732 kB

VmStk: 88 kB

VmExe: 4 kB

VmLib: 17620 kB

VmPTE: 7404 kB

VmSwap: 0 kB

Threads: 108

SigQ: 0/23301

SigPnd: 0000000000000000

ShdPnd: 0000000000000000

SigBlk: 0000000000000000

SigIgn: 0000000000000002

SigCgt: 2000000181005ccd

CapInh: 0000000000000000

CapPrm: 0000000000000000

CapEff: 0000000000000000

CapBnd: ffffffffffffffff

Cpus_allowed: f

Cpus_allowed_list: 0-3

Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001

Mems_allowed_list: 0

voluntary_ctxt_switches: 1

nonvoluntary_ctxt_switches: 1

其中VmRSS表示就是占用的物理内存。Threads表示当前开启的线程数。

特别说明RSS【实际使用物理内存】的含义:resident set size, the non-swapped physical memory that a task has used (in kiloBytes). (alias rssize, rsz).

pmap

[~]$ pmap -d 12415

12415: /usr/local/env/jdk1.8/bin/java -server -Xmx1024M -Xms1024M -Xmn512M -XX:MaxMetaspaceSize=128M -XX:MetaspaceSize=128M -XX:MaxDirectMemorySize=128M -XX:+UseConcMarkSweepGC -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses -XX:+CMSClassUnloadingEnabled -XX:+ParallelRefProcEnabled -XX:+CMSScavengeBeforeRemark -XX:-HeapDumpOnOutOfMemoryError -XX:+UseFastAccessorMethods -Xss256k -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=7 -XX:GCTimeRatio

Address Kbytes Mode Offset Device Mapping

0000000000400000 4 r-x-- 0000000000000000 0fc:00001 java

0000000000600000 4 rw--- 0000000000000000 0fc:00001 java

000000000116d000 996 rw--- 0000000000000000 000:00000 [ anon ]

00000000c0000000 1063680 rw--- 0000000000000000 000:00000 [ anon ]

0000000100ec0000 1033472 ----- 0000000000000000 000:00000 [ anon ]

0000003112e00000 88 r-x-- 0000000000000000 0fc:00001 libgcc_s-4.4.7-20120601.so.1

0000003112e16000 2044 ----- 0000000000016000 0fc:00001 libgcc_s-4.4.7-20120601.so.1

0000003113015000 4 rw--- 0000000000015000 0fc:00001 libgcc_s-4.4.7-20120601.so.1

00007f2c7d4a8000 12 r--s- 0000000000020000 0fc:00001 start.jar

00007f2c7d4ab000 4 rw--- 0000000000000000 000:00000 [ anon ]

00007f2c7d4ac000 4 r---- 0000000000000000 000:00000 [ anon ]

00007f2c7d4ad000 4 rw--- 0000000000000000 000:00000 [ anon ]

00007ffddeeed000 84 rw--- 0000000000000000 000:00000 [ stack ]

00007ffddef12000 4 r-x-- 0000000000000000 000:00000 [ anon ]

ffffffffff600000 4 r-x-- 0000000000000000 000:00000 [ anon ]

mapped: 6732236K writeable/private: 3786640K shared: 10820K

为方便展示省去中间部分内容

这里看pmap重点是最后一行,进程实际使用的物理内存是writeable/private: 3786640K。

其他几个点是什么意思呢?linux 会把一些shared libraries 载入到内存中,在pmap 的输出中,这些shared libraries 的名字通常是 lib*.so 。如 libX11.so.6.2.0 。这个 libX11.so.6.2.0 会被很多process load 到自己的运行环境中。上面展示的mapped的内存就包含这部分和其他进程共享的内存【pmap is reporting virtual memory statistics which match top VIRT column . This is including data shared with other processes and other pages stored on disk.】。

google perf

gperftools是google开发的一款非常实用的工具集,主要包括:性能优异的malloc free内存分配器tcmalloc;基于tcmalloc的堆内存检测和内存泄漏分析工具heap-profiler,heap-checker;基于tcmalloc实现的程序CPU性能监测工具cpu-profiler。可以对CPU时间片、内存等系统资源的分配合使用进行分析。使用perf对一个程序分析一般分为下面几个步骤:

加入对google-perftools库的依赖

运行目标程序,并用某种方式启动/终止剖析函数并产生剖析结果

运行剖析结果转换工具,江不可读的结果转化成某种格式的文档(pdf,txt,image等)

原理:该工具主要利用了unix的一个环境变量LD_PRELOAD,它允许你要加载的动态库优先加载起来,相当于一个Hook,于是可以针对同一个函数可以选择不同的动态库里的实现了,比如googleperftools就是将malloc方法替换成了tcmalloc的实现,这样就可以跟踪内存分配路径了。可以理解为在分配内存的同时增加内存分配跟踪的功能。

下面简单说下针对JVM的分析过程:

在JVM参数中增加下面的配置:

export LD_PRELOAD=/usr/lib64/libtcmalloc.so

export HEAPPROFILE=/home/lg/temp

export HEAP_PROFILE_ALLOCATION_INTERVAL= 1073741824

LD_PRELOAD

perftools一切都是以tcmalloc为基础。这里指定tcmalloc的安装位置;

HEAPPROFILE

指定heap profile存放的位置

HEAP_PROFILE_ALLOCATION_INTERVAL

每当一定量的内存被新申请分配出来时,就会输出profile文件,这个变量值就是控制多少字节。默认值是102410241024byte【1G】。一般情况下会调小一些。

运行程序输出heap文件

在jvm中加入上面的参数后,启动程序。这时候日志中会显示类似下面的内容:

Dumping heap profile to /home/lg/temp/_10030.0001.heap (1755151 MB allocated cumulatively, 1267 MB currently in use)

显示累计的对外内存的分配和当前使用的对外内存的大小。同时配置的对应的目录中会产生.heap文件。接下来的工作就是分析这些文件。

通过命令行分析文件

命令:

pprof --text /usr/local/env/jdk1.8/bin/java _10030.0001.heap

输出结果:

Using local file /usr/local/env/jdk1.8/bin/java.

Using local file _10030.0001.heap.

Total: 0.1 MB

0.0 83.9% 83.9% 0.1 99.9% __FRAME_END__

0.0 6.1% 90.0% 0.0 6.1% read_alias_file

0.0 5.6% 95.6% 0.0 5.6% _nl_intern_locale_data

0.0 3.1% 98.6% 0.0 3.1% _nl_make_l10nflist

0.0 0.7% 99.3% 0.0 0.7% __gconv_lookup_cache

0.0 0.3% 99.6% 0.0 0.3% strdup

0.0 0.2% 99.8% 0.0 5.8% _nl_load_locale_from_archive

0.0 0.1% 99.9% 0.0 0.7% __wcsmbs_load_conv

0.0 0.1% 99.9% 0.0 0.1% std::basic_string::_Rep::_S_create

0.0 0.0% 100.0% 0.0 0.0% set_binding_values

0.0 0.0% 100.0% 0.0 0.0% new_composite_name

0.0 0.0% 100.0% 0.0 0.0% 00007f5e3a5f3de1

0.0 0.0% 100.0% 0.0 0.1% 00007f5e3a5f3dc0

0.0 0.0% 100.0% 0.0 0.1% 00007f5e3a602405

0.0 0.0% 100.0% 0.0 0.1% 0x00007ffc250bc6e0

0.0 0.0% 100.0% 0.0 0.1% 0x2f6c61636f6c2f71

0.0 0.0% 100.0% 0.0 9.2% __dcigettext

0.0 0.0% 100.0% 0.0 0.7% __gconv_find_transform

0.0 0.0% 100.0% 0.1 89.5% __libc_start_main

0.0 0.0% 100.0% 0.0 0.1% _init

0.0 0.0% 100.0% 0.0 0.1% _init (inline)

0.0 0.0% 100.0% 0.0 6.1% _nl_expand_alias

0.0 0.0% 100.0% 0.0 9.2% _nl_find_domain

0.0 0.0% 100.0% 0.0 5.8% _nl_find_locale

0.0 0.0% 100.0% 0.0 0.0% bindtextdomain

0.0 0.0% 100.0% 0.0 0.7% mblen

0.0 0.0% 100.0% 0.0 0.7% mbrtowc

0.0 0.0% 100.0% 0.0 6.1% setlocale

0.0 0.0% 100.0% 0.0 0.1% std::basic_string::basic_string

0.0 0.0% 100.0% 0.0 0.1% std::basic_string::copy

0.0 0.0% 100.0% 0.0 7.6% strerror

0.0 0.0% 100.0% 0.0 7.6% strerror_r

0.0 0.0% 100.0% 0.0 0.0% textdomain

以上不是实际问题的数据

结果代表的含义:

c1 Number of profiling samples in this function(函数分析样本数量)

c2 Percentage of profiling samples in this function(函数分析样本的百分比)

c3 Percentage of profiling samples in the functions printed so far(

到目前为止打印的函数中的分析样本的百分比)

c4 Number of profiling samples in this function and its callees(

此函数及其被调用者的性能分析样本数)

c5 Percentage of profiling samples in this function and its callees(此函数及其被调用者的性能分析样本的百分比)

c5 Function name

通过perftools可以定位可能引起问题的函数或者有嫌疑的内存地址。针对JVM进程可能需要进一步借用其他工具来分析。

下一篇再介绍JVM相关的工具。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值