首页 - 推荐新闻 - 尿毒症,周记怎么写,极品家丁-批评谬论,还原真理,直达真相,我们带你看澎湃新闻

尿毒症,周记怎么写,极品家丁-批评谬论,还原真理,直达真相,我们带你看澎湃新闻

发布时间:2019-07-12  分类:推荐新闻  作者:admin  浏览:207

导言

Java言语的一个十分重要的特色便是与渠道的无关性。而运用Java虚拟机是完结这一特色的要害。一般的高档言语假如要在不同的渠道上运转,至少需求编译成不同的方针代码。而引进Java言语虚拟机后,Java言语在不同渠道上运转时不需求从头编译。Java言语运用Java虚拟机屏蔽了与具体渠道相关的信息,使得Java言语编译程序只需生成在Java虚拟机上运转的方针代码(字节码),就能够在多种渠道上不加修正地运转。Java虚拟机在履行字节码时,把字节码解说成具体渠道上的机器指令履行。这便是Java的能够“一次编译,处处运转”的原因。

jconsole – jconsole是依据Java Management Extensions (JMX)的实时图形化监测东西,这个东西运用了内建到JVM里边的JMX指令来供给实时的功用和资源的监控,包含了Java 程序的内存运用,Heap size, 线程的状况,类的分配状况和空间运用等等。

jinfo – jinfo能够从core文件里边知道溃散的Java运用程序的装备信息,现在只需在Solaris和Linux的JDK版别里边才有。

jmap – jmap 能够从core文件或进程中取得内存的具体匹配状况,包含Heap size, Perm size等等,现在只需在Solaris和Linux的JDK版别里边才有。

jdb – jdb 用来对core文件和正在运转的Java进程进行实时地调试,里边包含了丰厚的指令帮助您进行调试,它的功用和Sun studio里边所带的dbx十分相似,但 jdb是专门用来针对Java运用程序的。

jstat – jstat运用了JVM内建的指令对Java运用程序的资源和功用进行实时的指令行的监控,包含了对Heap size和废物收回状况的监控等等。

jps – jps是用来查看JVM里边一切进程的具体状况, 包含进程ID,进程发动的途径等等。

jstatd

发动jvm监控服务。它是一个依据rmi的运用,向长途机器供给本机jvm运用程序的信息。默许端口1099。

实例:jstatd -J-Djava.security.policy=my.policy

my.policy文件需求自己树立,内如如下:

grant codebase "file:$JAVA_HOME/lib/tools.jar" { permission java.security.AllPermission; };

这是安全战略文件,因为jdk对jvm做了jaas的安全检测,所以咱们有必要设置一些战略,使得jstatd被容许作网络操作

上面的操作没有经过,呈现:

Could not create remote objectaccess denied (java.util.PropertyPermission java.rmi.server.ignoreSubClasses write)java.security.AccessControlException: access denied (java.util.PropertyPermission java.rmi.server.ignoreSubClasses write)at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)at java.security.AccessController.checkPermission(AccessController.java:546)at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)at java.lang.System.setProperty(System.java:727)at sun.tools.jstatd.Jstatd.main(Jstatd.java:122)

create in your usr/java/bin the jstatd.all.policy file, with the content must be

grant codebase "file:${java.home}/../lib/tools.jar" { permission java.security.AllPermission; };

JPS

列出一切的jvm实例

实例:

jps

列出本机一切的jvm实例

jps 192.168.0.77

列出长途服务器192.168.0.77机器一切的jvm实例,选用rmi协议,默许衔接端口为1099(条件是长途服务器供给jstatd服务)

输出内容如下:

jones@jones:~/data/ebook/java/j2se/jdk_gc$ jps

6286 Jps

6174 Jstat

jconsole

一个图形化界面,能够调查到java进程的gc,class,内存等信息。虽然比较直观,可是个人仍是比较倾向于运用jstat指令(在最终一部分会对jstat作具体的介绍)。

jinfo (linux下特有)

调查运转中的java程序的运转环境参数:参数包含Java System特点和JVM指令行参数

实例:jinfo 2083

其间2083便是java进程id号,能够用jps得到这个id号。

输出内容太多了,不在这儿一一列举,咱们能够自己测验这个指令。

jstack (linux下特有)

能够调查到jvm中其时一切线程的运转状况和线程其时状况

jstack 2083

输出内容如下:

jmap (linux下特有,也是很常用的一个指令)

调查运转中的jvm物理内存的占用状况。

参数如下:

-heap :打印jvm heap的状况-histo: 打印jvm heap的直方图。其输出信息包含类名,目标数量,目标占用巨细。-histo:live : 同上,可是只容许存活目标的状况-permstat: 打印permanent generation heap状况

指令运用:

jmap -heap 2083

能够调查到New Generation(Eden Space,From Space,To Space),tenured generation,Perm Generation的内存运用状况

输出内容:

jmap -histo 2083 | jmap -histo:live 2083

能够调查heap中一切目标的状况(heap中一切生计的目标的状况)。包含目标数量和所占空间巨细。

输出内容:

写个脚本,能够很快把占用heap最大的目标找出来,抵挡内存走漏特别有用。

jstat

最终要要点介绍下这个指令。

这是jdk指令中比较重要,也是恰当有用的一个指令,能够调查到classloader,compiler,gc相关信息

具体参数如下:

-class:计算class loader行为信息

-compile:计算编译行为信息

-gc:计算jdk gc时heap信息

-gccapacity:计算不同的generations(不知道怎样翻译好,包含重生区,晚年区,permanent区)相应的heap容量状况

-gccause:计算gc的状况,(同-gcutil)和引起gc的事情

-gcnew:计算gc时,重生代的状况

-gcnewcapacity:计算gc时,重生代heap容量

-gcold:计算gc时,晚年区的状况

-gcoldcapacity:计算gc时,晚年区heap容量

-gcpermcapacity:计算gc时,permanent区heap容量

-gcutil:计算gc时,heap状况

-printcompilation:不知道干什么的,一向没用过。

一般比较常用的几个参数是:

jstat -class 2083 1000 10 (每隔1秒监控一次,总共做10次)

输出内容意义如下:

LoadedNumber of classes loaded.BytesNumber of Kbytes loaded.UnloadedNumber of classes unloaded.BytesNumber of Kbytes unloaded.TimeTime spent performing class load and unload operations.

jstat -gc 2083 2000 20(每隔2秒监控一次,共做10)

输出内容意义如下:

S0CCurrent survivor space 0 capacity (KB).ECCurrent eden space capacity (KB).EUEden space utilization (KB).OCCurrent old space capacity (KB).OUOld space utilization (KB).PCCurrent permanent space capacity (KB).PUPermanent space utilization (KB).YGCNumber of young generation GC Events.YGCTYoung generation garbage collection time.FGCNumber of full GC events.FGCTFull garbage collection time.GCTTotal garbage collection time.

输出内容:

假如能娴熟运用这些指令,尤其是在linux下,那么完全能够替代jprofile等监控东西了,谁让它收费呢。呵呵。用指令的优点便是速度快,而且辅助于其他指令,比方grep gawk sed等,能够拼装多种契合自己需求的东西。

jps 的用法

用来查看 JVM 里边一切进程的具体状况 , 包含进程 ID ,进程发动的途径等等。 与 unix 上的 ps 相似,用来显现本地的 java 进程,能够查看本地运转着几个 java 程序,并显现他们的进程号。

[root@localhost ~]# jps

25517 Jps

25444 Bootstrap

jstack 的用法

假如 java 程序溃散生成 core 文件, jstack 东西能够用来取得 core 文件的 java stack 和 native stack 的信息,然后能够轻松地知道 java 程序是怎么溃散和在程序何处发作问题。别的, jstack 东西还能够隶属到正在运转的 java 程序中,看到其时运转的 java 程序的 java stack 和 native stack 的信息 , 假如现在运转的 java 程序呈现 hung 的状况, jstack 是十分有用的。现在只需在 Solaris 和 Linux 的 JDK 版别里边才有。

[root@localhost bin]# jstack 25444

Attaching to process ID 25917, please wait...

Debugger attached successfully.

Client compiler detected.

JVM version is 1.5.0_08-b03

Thread 25964: (state = BLOCKED)

Error occurred during stack walking:

sun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a lwp

at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$LinuxDebuggerLocalWorkerThread.execute(LinuxDebuggerLocal.java:134)

at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.getThreadIntegerRegisterSet(LinuxDebuggerLocal.java:437)

at sun.jvm.hotspot.debugger.linux.LinuxThread.getContext(LinuxThread.java:48)

at

jstat 的用法

用以判别JVM 是否存在内存问题呢?怎么判别JVM 废物收回是否正常?一般的top 指令底子上满意不了这样的需求,因为它首要监控的是整体的体系资源,很难定位到java 运用程序。

Jstat 是JDK 自带的一个轻量级小东西。全称“Java Virtual Machine statistics monitoring tool” ,它坐落java 的bin 目录下,首要运用JVM 内建的指令对Java 运用程序的资源和功用进行实时的指令行的监控,包含了对Heap size 和废物收回状况的监控。可见,Jstat 是轻量级的、专门针对JVM 的东西,十分适用。因为JVM 内存设置较大,图中百分比改变不太显着

一个极强的监督 VM 内存东西。能够用来监督 VM 内存内的各种堆和非堆的巨细及其内存运用量。

jstat 东西特别强壮,有很多的可选项,具体查看堆内各个部分的运用量,以及加载类的数量。运用时,需加上查看进程的进程 id ,和所选参数。

语法结构:

Usage: jstat -help|-options

jstat -

参数解说:

Options — 选项,咱们一般运用 -gcutil 查看gc 状况

vmid — VM 的进程号,即其时运转的java 进程号

interval– 间隔时刻,单位为秒或许毫秒

count — 打印次数,假如缺省则打印无数次

S0 — Heap 上的 Survivor space 0 区已运用空间的百分比

S1 — Heap 上的 Survivor space 1 区已运用空间的百分比

E — Heap 上的 Eden space 区已运用空间的百分比

O — Heap 上的 Old space 区已运用空间的百分比

P — Perm space 区已运用空间的百分比

YGC — 从运用程序发动到采样时发作 Young GC 的次数

YGCT– 从运用程序发动到采样时 Young GC 所用的时刻( 单位秒 )

FGC — 从运用程序发动到采样时发作 Full GC 的次数

FGCT– 从运用程序发动到采样时 Full GC 所用的时刻( 单位秒 )

GCT — 从运用程序发动到采样时用于废物收回的总时刻( 单位秒)

jstat –gccapacity : 能够显现, VM 内存中三代( young,old,perm )目标的运用和占用巨细,如: PGCMN 显现的是最小 perm 的内存运用量, PGCMX 显现的是 perm 的内存最大运用量, PGC 是其时重生成的 perm 内存占用量, PC 是但前 perm 内存占用量。其他的能够依据这个类推, OC 是 old 内纯的占用量。

[root@localhost bin]# jstat -gccapacity 25917

NGCMN 640.0

NGCMX 4992.0

NGC 832.0

S0C 64.0

S1C 64.0

EC 704.0

OGCMN 1408.0

OGCMX 60544.0

OGC 9504.0

OC 9504.0 OC 是 old 内纯的占用量

PGCMN 8192.0 PGCMN 显现的是最小 perm 的内存运用量

PGCMX 65536.0 PGCMX 显现的是 perm 的内存最大运用量

PGC 12800.0 PGC 是其时重生成的 perm 内存占用量

PC 12800.0 PC 是但前 perm 内存占用量

YGC 164

FGC 6

jmap 的用法

打印出某个 java 进程(运用 pid )内存内的,一切 ‘ 目标 ’ 的状况(如:发作那些目标,及其数量)。

能够输出一切内存中目标的东西,乃至能够将 VM 中的 heap ,以二进制输出成文本。运用办法 jmap -histo pid 。假如连用 SHELL jmap -histo pid>a.log 能够将其保存到文本中去,在一段时刻后,运用文本比照东西,能够比照出 GC 收回了哪些目标。

jinfo 的用法

能够输出并修正运转时的 java 进程的 opts 。用途比较简略,便是能输出并修正运转时的 java 进程的运转参数。用法是 jinfo -opt pid 如:查看 2788 的 MaxPerm 巨细能够用 jinfo -flag MaxPermSize 2788 。

jconsole 的用法

jconsole: 一个 java GUI 监督东西,能够以图表化的办法显现各种数据。并可经过长途衔接监督长途的服务器 VM 。

用 java 写的 GUI 程序,用来监控 VM ,并可监控长途的 VM ,十分易用,而且功用十分强。指令行里打 jconsole ,选则进程就能够了

jmap 的用法

打印出某个 java 进程(运用 pid )内存内的,一切 ‘ 目标 ’ 的状况(如:发作那些目标,及其数量)。

能够输出一切内存中目标的东西,乃至能够将 VM 中的 heap ,以二进制输出成文本。运用办法 jmap -histo pid 。假如连用 SHELL jmap -histo pid>a.log 能够将其保存到文本中去,在一段时刻后,运用文本比照东西,能够比照出 GC 收回了哪些目标。

原理

内存分配战略

首要咱们来了解程序运转时,所需内存的分配战略:

依照编译原理的观念,程序运转时的内存分配有三种战略,分别是静态的,栈式的,和堆式的,对应的,三种存储战略运用的内存空间首要分别是静态存储区(也称办法区)、堆区和栈区。他们的功用不同,对他们运用办法也就不同。

静态存储区(办法区):内存在程序编译的时分就现已分配好,这块内存在程序整个运转期间都存在。它首要寄存静态数据、大局static数据和常量。

栈区:在履行函数时,函数内局部变量的存储单元都能够在栈上创立,函数履行完毕时这些存储单元主动被开释。栈内存分配运算内置于处理器的指令会集,功率很高,可是分配的内存容量有限。

堆区:亦称动态内存分配。程序在运转的时分用malloc或new请求恣意巨细的内存,程序员自己担任在恰当的时分用free或delete开释内存(Java则依靠废物收回器)。动态内存的生计期能够由咱们决议,假如咱们不开释内存,程序将在最终才开释掉动态内存。 可是,杰出的编程习气是:假如某动态内存不再运用,需求将其开释掉。

在函数中(阐明是局部变量)界说的一些底子类型的变量和目标的引证变量都是在函数的栈内存中分配。当在一段代码块中界说一个变量时,java就在栈中为这个变量分配内存空间,当超越变量的效果域后,java会主动开释掉为该变量分配的内存空间,该内存空间能够马上被另作他用。

堆内存用于寄存一切由new创立的目标(内容包含该目标其间的一切成员变量)和数组。在堆中分配的内存,由java虚拟机主动废物收回器来办理。在堆中发作了一个数组或许目标后,还能够在栈中界说一个特别的变量,这个变量的取值等于数组或许目标在堆内存中的首地址,在栈中的这个特别的变量就变成了数组或许目标的引证变量,今后就能够在程序中运用栈内存中的引证变量来拜访堆中的数组或许目标,引证变量恰当于为数组或许目标起的一个别号,或许代号。

堆是不接连的内存区域(因为体系是用链表来存储闲暇内存地址,天然不是接连的),堆巨细受限于计算机体系中有用的虚拟内存(32bit体系理论上是4G),所以堆的空间比较灵敏,比较大。栈是一块接连的内存区域,巨细是操作体系预定好的,windows下栈巨细是2M(也有是1M,在编译时确认,VC中可设置)。

为什么内存走漏

为了判别Java中是否有内存走漏,咱们首要有必要了解Java是怎么办理(堆)内存的。Java的内存办理便是目标的分配和开释问题。在Java中,内存的分配是由程序完结的,而内存的开释是由废物收集器(Garbage Collection,GC)完结的,程序员不需求经过调用函数来开释内存,但它只能收回无用而且不再被其它目标引证的那些目标所占用的空间。

Java的内存废物收回机制是从程序的首要运转目标(如静态目标/寄存器/栈上指向的堆内存目标等)开端查看引证链,当遍历一遍后得到上述这些无法收回的目标和他们所引证的目标链,组成无法收回的目标调集,而其他孤立目标(集)就作为废物收回。GC为了能够正确开释目标,有必要监控每一个目标的运转状况,包含目标的请求、引证、被引证、赋值等,GC都需求进行监控。监督目标状况是为了愈加精确地、及时地开释目标,而开释目标的底子准则便是该目标不再被引证。

在Java中,这些无用的目标都由GC担任收回,因而程序员不需求考虑这部分的内存走漏。虽然,咱们有几个函数能够拜访GC,例如运转GC的函数System.gc(),可是依据Java言语标准界说,该函数不确保JVM的废物收集器必定会履行。因为不同的JVM完结者或许运用不同的算法办理GC。一般GC的线程的优先等级较低。JVM调用GC的战略也有很多种,有的是内存运用抵达必定程度时,GC才开端作业,也有守时履行的,有的是陡峭履行GC,有的是中止式履行GC。但一般来说,咱们不需求关怀这些。

堆内存中的长生命周期的目标持有短生命周期目标的强/软引证,虽然短生命周期目标现已不再需求,可是因为长生命周期目标持有它的引证而导致不能被收回,这便是Java中内存走漏的底子原因`。

内存走漏常见原因

调集类

调集类假如仅仅有增加元素的办法,而没有相应的删去机制,导致内存被占用。假如这个调集类是大局性的变量 (比方类中的静态特点,大局性的 map 等即有静态引证或 final 一向指向它),那么没有相应的删去机制,很或许导致调集所占用的内存只增不减。

Android 组件或特别调集目标的运用

BroadcastReceiver,ContentObserver,FileObserver,Cursor,Callback等在 Activity onDestroy 或许某类生命周期完毕之后必定要 unregister 或许 close 掉,不然这个 Activity 类会被 system 强引证,不会被内存收回。

不要直接对 Activity 进行直接引证作为成员变量,假如不得不这么做,请用 private WeakReference mActivity 来做,相同的,关于Service 等其他有自己声明周期的目标来说,直接引证都需求慎重考虑是否会存在内存走漏的或许。

Handler

要知道,只需 Handler 发送的 Message 尚未被处理,则该 Message 及发送它的 Handler 目标将被线程 MessageQueue 一向持有。因为 Handler 归于 TLS(Thread Local Storage) 变量, 生命周期和 Activity 是不一致的。因而这种完结办法一般很难确保跟 View 或许 Activity 的生命周期保持一致,故很简略导致无法正确开释。如上所述,Handler 的运用要尤为当心,不然将很简略导致内存走漏的发作。

Thread 内存走漏

线程也是形成内存走漏的一个重要的源头。线程发作内存走漏的首要原因在于线程生命周期的不可控。比方线程是 Activity 的内部类,则线程目标中保存了 Activity 的一个引证,当线程的 run 函数耗时较长没有完毕时,线程目标是不会被毁掉的,因而它所引证的老的 Activity 也不会被毁掉,因而就呈现了内存走漏的问题。

异步线程未完结前退出 Activity 等组件,或许会导致界面资源无法开释。

这种状况是典型的线程目标导致的内存走漏。原因也很简略,线程 Thread 目标的 run 使命未履行完之前,目标自身是不会开释的。因而 Activity 等组件目标内的线程目标成员假如有耗时使命(一般也都是耗时使命),就会导致一向持有组件自身的引证内存走漏!

本文部分内容和经历摘自网络,结合本次内存走漏的排查总结予以概括

东西

AS的Memory窗口

能够图表的办法显现内存状况 - 闲暇内存 & 已运用内存.

adb shell dumpsys meminfo com.mogujie

十分好的东西 能够显现java heap 、 native heap、同享内存、仓库信息。

MAT

Eclipse Memory Analysis Tools(点我下载)是一个专门剖析Java堆数据内存引证的东西,咱们能够运用它便利的定位内存走漏原因,中心使命便是找到GC ROOT方位即可,哎呀,关于这个东西的运用我是真的不想说了,自己查找吧,真实简略、传统的不行了。

PS:这是开发中运用频率十分高的一个东西之一,费事必须把握其中心运用技巧

DDMS-Heap

DDMS 自带的内存剖析东西 比较简略 运用频度不高

leakcanary

leakcanary是一个开源项目,一个内存走漏主动检测东西,是闻名的GitHub开源安排Square奉献的,它的首要优势就在于主动化过早的发觉内存走漏、装备简略、抓取交心,缺陷在于还存在一些bug,不过正常运用百分之九十状况是OK的,其中心原理与MAT东西相似。

总结

以 上便是我对Java开发大型互联网高档结构内存走漏之JVM监控实战原理 问题及其优化总结,共享给咱们,觉得收成的话能够点个重视保藏转发一波喔,谢谢大佬们支撑!

最终,每一位读到这儿的网友,感谢你们本领心肠看完。期望在成为一名更优异的Java程序员的道路上,咱们能够一同学习、一同前进!都能赢取白富美,走向架构师的人生巅峰!

想了解学习Java方面的技能内容以及Java技能视频的内容可加群:722040762 验证码:头条(06 必过)欢迎咱们的参加哟!

下一篇
快捷导航
最新发布
标签列表