加入收藏 | 设为首页 | 会员中心 | 我要投稿 河北网 (https://www.hebeiwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 业界 > 正文

值得阅读的内存泄漏说明总结和Tomcat调优

发布时间:2019-02-28 19:41:10 所属栏目:业界 来源:今日头条
导读:写在最前面,运行情形:tomcat8,jdk1.8,windows server 2008内存16G,软件LoadRunner11,MAT和JProfile9.1。 题目描写:前段时刻碰着一个很稀疏的题目,开拓的WEB应用,常常会毫无症状的宕掉,然后抓了线程栈看下,发明之前写的数据库链接池呈现了阻塞的
副问题[/!--empirenews.page--]

写在最前面,运行情形:tomcat8,jdk1.8,windows server 2008内存16G,软件LoadRunner11,MAT和JProfile9.1。

题目描写:前段时刻碰着一个很稀疏的题目,开拓的WEB应用,常常会毫无症状的宕掉,然后抓了线程栈看下,发明之前写的数据库链接池呈现了阻塞的题目,后头说明代码发明同步锁谁人处全部一些题目,呈现非常也许导致锁不开释,造成堵塞,然后其他线程全block住了,然后应用卡住了,最后就挂了。后头换成了开源的DBPC毗连池,获取数据库链接卡住的题目就办理了。可是又发明白一个新题目,用LoadRunner做压力测试时发明tomcat占用的内存一连上升,压了一段时刻停了再继承压,tomcat占用内存不会开释,继承往上涨,第一回响就是猜疑存在内存泄漏,于是继承往下研究。

值得阅读的内存泄漏说明总结和Tomcat调优

因为之前毫无说明内存泄漏的履历,对JVM的内存分派和接纳机制也不算相识,纯小白一个,以是只能看《深入领略Java假造机》和从网上查各类资料。

Part1.JVM内存构成先容

这里先先容一下JVM的内存构成,如下图所示:

JVM 将内存地区分别为 MethodArea(Non-Heap)(要领区),Heap(堆),Program Counter Register(措施计数器), VM

Stack(假造机栈,也有翻译成JAVA 要领栈的),Native Method Stack (当处所法栈),个中Method Area和Heap是线程共享的,VMStack,Native

Method Stack 和Program Counter Register长短线程共享的。

那我们的措施是怎么在这些内存上运行的呢,归纳综合地说来,JVM初始运行的时辰城市分派好Method Area(要领区)和Heap(堆),而JVM 每碰着一个线程(当前景象下WEB应用前台的一个数据哀求发送到靠山对应就是启动了一个线程),就为其分派一个Program Counter Register(措施计数器),VM

Stack(假造机栈)和Native Method Stack (当处所法栈),当线程终止时,三者(假造机栈,当处所法栈和措施计数器)所占用的内存空间也会被开释掉。非线程共享的那三个地区的生命周期与所属线程沟通,而线程共享的地区与JAVA措施运行的生命周期沟通,以是这也是体系垃圾接纳的场合只产生在线程共享的地区(现实上对大部门假造机来说知产生在Heap上)的缘故起因。

1.措施计数器

2.VM Strack

先来相识下JAVA指令的组成:

JAVA指令由 操纵码 (要领自己)和 操纵数 (要领内部变量) 构成,着实底层都是系统布局和构成道理内里学的对象。

1)要领自己是指令的操纵码部门,生涯在Stack中;

2)要领内部变量(局部变量)作为指令的操纵数部门,跟在指令的操纵码之后,生涯在Stack中(现实上是简朴范例(int,byte,short 等)生涯在Stack中,工具范例在Stack中生涯地点(相等于指针内里的地点),在Heap 中生涯值);

假造机栈也叫栈内存,是在线程建设时建设,它的生命期是跟从线程的生命期,线程竣事栈内存也就开释,对付栈来说不存在垃圾接纳题目,只要线程一竣事,该栈就 Over,以是不存在垃圾接纳。也有一些资料翻译成JAVA要领栈,或许是由于它所描写的是java要领执行的内存模子,每个要领执行的同时建设帧栈(Strack Frame)用于存储局部变量表(包括了对应的要领参数和局部变量),操纵栈(Operand Stack,记录出栈、入栈的操纵),动态链接、要领出口等信息,每个要领被挪用直到执行完毕的进程,对应这帧栈在假造机栈的入栈和出栈的进程。

局部变量表存放了编译期可知的各类根基数据范例(boolean、byte、char、short、int、float、long、double)、工具的引用(reference范例,不等同于工具自己,按照差异的假造机实现,也许是一个指向工具起始地点的引用指针,也也许是一个代表工具的句柄可能其他与工具相干的位置)和 returnAdress范例(指向下一条字节码指令的地点)。局部变量表所需的内存空间在编译时代完因素派,在要领在运行之前,该局部变量表所必要的内存空间是牢靠的,运行时代也不会改变。

栈帧是一个内存区块,是一个数据集,是一个有关要领(Method)和运行期数据的数据集,当一个要领 A 被挪用时就发生了一个栈帧 F1,并被压入到栈中,A 要领又挪用了 B 要领,于是发生栈帧 F2 也被压入栈,执行完毕后,先弹出 F2栈帧,再弹出 F1 栈帧,遵循“先辈后出”原则。如下图所示:

3.Heap

Heap(堆)是JVM的内存数据区。Heap 的打点很伟大,是被全部线程共享的内存地区,在JVM启动时辰建设,专门用来生涯工具的实例。在Heap 平分派必然的内存来生涯工具实例,现实上壹贝偾生涯工具实例的属性值,属性的范例和工具自己的范例标志等,并不生涯工具的要领(以帧栈的情势生涯在Stack中),在Heap 平分派必然的内存生涯工具实例。而工具实例在Heap 平分派好往后,必要在Stack中生涯一个4字节的Heap 内存地点,用来定位该工具实例在Heap 中的位置,便于找到该工具实例,是垃圾接纳的首要场合。java堆处于物理不持续的内存空间中,只要逻辑上持续即可。下面我们还会着重先容一下这块地区。

4.Method Area

Object Class Data(加载类的类界说数据) 是存储在要领区的。除此之外,常量、静态变量、JIT(即时编译器)编译后的代码也都在要领区。正由于要领区所存储的数据与堆有一种类比相关,以是它还被称为 Non-Heap。要领区也可所以内存不持续的地区构成的,而且可配置为牢靠巨细,也可以配置为可扩展的,这点与堆一样。

垃圾接纳在这个地区会较量少呈现,这个地区内存接纳的目标首要针对常量池的接纳和类的卸载。

5.运行时常量池(Runtime Constant Pool)

要领区内部有一个很是重要的地区,叫做运行时常量池(Runtime Constant Pool,简称 RCP)。在字节码文件(Class文件)中,除了有类的版本、字段、要领、接口等先关信息描写外,尚有常量池(Constant Pool Table)信息,用于存储编译器发生的字面量和标记引用。这部门内容在类被加载后,城市存储到要领区中的RCP。值得留意的是,运行时发生的新常量也可以被放入常量池中,好比 String 类中的 intern() 要领发生的常量。

常量池就是这个范例用到的常量的一个有序荟萃。包罗直接常量(根基范例,String)和对其他范例、要领、字段的标记引用.譬喻:

类和接口的全限命名;

字段的名称和描写符;

要领和名称和描写符。

池中的数据和数组一样通过索引会见。因为常量池包括了一个范例全部的对其他范例、要领、字段的标记引用,以是常量池在Java的动态链接中起了焦点浸染。

6.NativeMethod Stack

与VM Strack相似,VM Strack为JVM提供执行JAVA要领的处事,Native

Method Stack则为JVM提供行使native 要领的处事。

7.直接内存区

(编辑:河北网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读