jprofilerlinux
① tomcat编译内存溢出怎么解决
JVM管理两种类型的内存,堆和非堆。堆是给开发人员用的上面说的就是,是在JVM启动时创建;非堆是留给JVM自己用的,用来存放类的信息的。它和堆不同,运行期内GC不会释放空间。 一、内存溢出类型
1、java.lang.OutOfMemoryError: PermGen space
JVM管理两种类型的内存,堆和非堆。堆是给开发人员用的上面说的就是,是在JVM启动时创建;非堆是留给JVM自己用的,用来存放类的信息的。它和堆不同,运行期内GC不会释放空间。如果web app用了大量的第三方jar或者应用有太多的class文件而恰好MaxPermSize设置较小,超出了也会导致这块内存的占用过多造成溢出,或者tomcat热部署时侯不会清理前面加载的环境,只会将context更改为新部署的,非堆存的内容就会越来越多。
PermGen space的全称是Permanent Generation space,是指内存的永久保存区域,这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中,它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的应用中有很CLASS的话,就很可能出现PermGen space错误,这种错误常见在web服务器对JSP进行pre compile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了。
一个最佳的配置例子:(经过本人验证,自从用此配置之后,再未出现过tomcat死掉的情况)
set JAVA_OPTS=-Xms800m -Xmx800m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m
2、java.lang.OutOfMemoryError: Javaheap space
第一种情况是个补充,主要存在问题就是出现在这个情况中。其默认空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4。如果内存剩余不到40%,JVM就会增大堆到Xmx设置的值,内存剩余超过70%,JVM就会减小堆到Xms设置的值。所以服务器的Xmx和Xms设置一般应该设置相同避免每次GC后都要调整虚拟机堆的大小。假设物理内存无限大,那么JVM内存的最大值跟操作系统有关,一般32位机是1.5g到3g之间,而64位的就不会有限制了。
注意:如果Xms超过了Xmx值,或者堆最大值和非堆最大值的总和超过了物理内存或者操作系统的最大限制都会引起服务器启动不起来。
垃圾回收GC的角色
JVM调用GC的频度还是很高的,主要两种情况下进行垃圾回收:
当应用程序线程空闲;另一个是java内存堆不足时,会不断调用GC,若连续回收都解决不了内存堆不足的问题时,就会报out of memory错误。因为这个异常根据系统运行环境决定,所以无法预期它何时出现。
根据GC的机制,程序的运行会引起系统运行环境的变化,增加GC的触发机会。
为了避免这些问题,程序的设计和编写就应避免垃圾对象的内存占用和GC的开销。显示调用System.GC()只能建议JVM需要在内存中对垃圾对象进行回收,但不是必须马上回收,
一个是并不能解决内存资源耗空的局面,另外也会增加GC的消耗。
二、JVM内存区域组成
简单的说java中的堆和栈
java把内存分两种:一种是栈内存,另一种是堆内存
1、在函数中定义的基本类型变量和对象的引用变量都在函数的栈内存中分配;
2、堆内存用来存放由new创建的对象和数组
在函数(代码块)中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量所分配的内存空间;在堆中分配的内存由java虚拟机的自动垃圾回收器来管理
堆的优势是可以动态分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的。缺点就是要在运行时动态分配内存,存取速度较慢;
栈的优势是存取速度比堆要快,缺点是存在栈中的数据大小与生存期必须是确定的无灵活性。
java堆分为三个区:New、Old和Permanent
GC有两个线程:
新创建的对象被分配到New区,当该区被填满时会被GC辅助线程移到Old区,当Old区也填满了会触发GC主线程遍历堆内存里的所有对象。Old区的大小等于Xmx减去-Xmn
java栈存放
栈调整:参数有+UseDefaultStackSize -Xss256K,表示每个线程可申请256k的栈空间
每个线程都有他自己的Stack
三、JVM如何设置虚拟内存
提示:在JVM中如果98%的时间是用于GC且可用的Heap size 不足2%的时候将抛出此异常信息。
提示:Heap Size 最大不要超过可用物理内存的80%,一般的要将-Xms和-Xmx选项设置为相同,而-Xmn为1/4的-Xmx值。
提示:JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。
默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。因此服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小。
提示:假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系。
简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,
这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,linux系统下为2G-3G),而64bit以上的处理器就不会有限制了
提示:注意:如果Xms超过了Xmx值,或者堆最大值和非堆最大值的总和超过了物理内存或者操作系统的最大限制都会引起服务器启动不起来。
提示:设置NewSize、MaxNewSize相等,"new"的大小最好不要大于"old"的一半,原因是old区如果不够大会频繁的触发"主" GC ,大大降低了性能
JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;
由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。
解决方法:手动设置Heap size
修改TOMCAT_HOME/bin/catalina.bat
在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:
JAVA_OPTS="-server -Xms800m -Xmx800m -XX:MaxNewSize=256m"
四、性能检查工具使用
定位内存泄漏:
JProfiler工具主要用于检查和跟踪系统(限于Java开发的)的性能。JProfiler可以通过时时的监控系统的内存使用情况,随时监视垃圾回收,线程运行状况等手段,从而很好的监视JVM运行情况及其性能。
1. 应用服务器内存长期不合理占用,内存经常处于高位占用,很难回收到低位
② jprofiler 9.2 怎么使用
:打开 菜单Session->Integeration Widzards ->new Server Integeration 第二步:选择 Generic Application Server->On a remote computer 第三步:JVM选择建议选择Oracle,根据实际情况选择Version和Mode。Mode选择使用的是interpreted。 第四步:选择wait for a connection from the Jprofiler GUI,点击next 第五步:Remote地址填写要连接的Linux下的IP:比如192.168.51.132 第六步:填写Linux下jprofiler的安装目录:如图所示 第七步:端口使用jprofiler默认的8849 后面的步骤点到Finish即可。
③ jprofiler 9.2 windows和linux的jdk可以不相同吗
Java™堆耗尽并不是造成java.lang.OutOfMemoryError的惟一原因。如果本机内存耗尽,则会发生普通调试技巧无法解决的OutOfMemoryError。本文将讨论本机内存的概念,Java运行时如何使用它,它被耗尽时会出现什么情况,以及如何在Windows®和Linux®上调试本机OutOfMemoryError。针对AIX®系统的相同主题将在另一篇同类文章中介绍。Java堆(每个Java对象在其中分配)是您在编写Java应用程序时使用最频繁的内存区域。JVM设计用于将我们与主机的特性隔离,所以将内存当作堆来考虑再正常不过了。您一定遇到过Java堆OutOfMemoryError,它可能是由于对象泄漏造成的,也可能是因为堆的大小不足以存储所有数据,您也可能了解这些场景的一些调试技巧。但是随着您的Java应用程序处理越来越多的数据和越来越多的并发负载,您可能就会遇到无法使用常规技巧进行修复的OutOfMemoryError。在一些场景中,即使java堆未满,也会抛出错误。当这类场景发生时,您需要理解Java运行时环境(JavaRuntimeEnvironment,JRE)内部到底发生了什么。Java应用程序在Java运行时的虚拟化环境中运行,但是运行时本身是使用C之类的语言编写的本机程序,它也会耗用本机资源,包括本机内存。本机内存是可用于运行时进程的内存,它与Java应用程序使用的java堆内存不同。每种虚拟化资源(包括Java堆和Java线程)都必须存储在本机内存中,虚拟机在运行时使用的数据也是如此。这意味着主机的硬件和操作系统施加在本机内存上的限制会影响到Java应用程序的性能。本系列文章共分两篇,讨论不同平台上的相应话题。本文是其中一篇。在这两篇文章中,您将了解什么是本机内存,Java运行时如何使用它,本机内存耗尽之后会发生什么情况,以及如何调试本机OutOfMemoryError。本文介绍Windows和Linux平台上的这一主题,不会介绍任何特定的运行时实现。另一篇类似的文章介绍AIX上的这一主题,着重介绍IBM®DeveloperKitforJava。(另一篇文章中关于IBM实现的信息也适合于除AIX之外的平台,因此如果您在Linux上使用IBMDeveloperKitforJava,或使用IBM32-,您会发现这篇文章也有用处)。本机内存简介我将首先解释一下操作系统和底层硬件给本机内存带来的限制。如果您熟悉使用C等语言管理动态内存,那么您可以直接跳到下一节。硬件限制本机进程遇到的许多限制都是由硬件造成的,而与操作系统没有关系。每台计算机都有一个处理器和一些随机存取存储器(RAM),后者也称为物理内存。处理器将数据流解释为要执行的指令,它拥有一个或多个处理单元,用于执行整数和浮点运算以及更高级的计算。处理器具有许多寄存器——常快速的内存元素,用作被执行的计算的工作存储,寄存器大小决定了一次计算可使用的最大数值。处理器通过内存总线连接到物理内存。物理地址(处理器用于索引物理RAM的地址)的大小限制了可以寻址的内存。例如,一个16位物理地址可以寻址0x0000到0xFFFF的内存地址,这个地址范围包括2^16=65536个惟一的内存位置。如果每个地址引用一个存储字节,那么一个16位物理地址将允许处理器寻址64KB内存。处理器被描述为特定数量的数据位。这通常指的是寄存器大小,但是也存在例外,比如32位390指的是物理地址大小。对于桌面和服务器平台,这个数字为31、32或64;对于嵌入式设备和微处理器,这个数字可能小至4。物理地址大小可以与寄存器带宽一样大,也可以比它大或小。如果在适当的操作系统上运行,大部分64位处理器可以运行32位程序。表1列出了一些流行的Linux和Windows架构,以及它们的寄存器和物理地址大小:表1.一些流行处理器架构的寄存器和物理地址大小架构寄存器带宽(位)物理地址大小(位)(现代)Intel®x86323236,具有物理地址扩展(PentiumPro和更高型号)x866464目前为48位(以后将会增大)PPC6464在POWER5上为50位39031位323139064位6464操作系统和虚拟内存如果您编写无需操作系统,直接在处理器上运行的应用程序,您可以使用处理器可以寻址的所有内存(假设连接到了足够的物理RAM)。但是要使用多任务和硬件抽象等特性,几乎所有人都会使用某种类型的操作系统来运行他们的程序。在Windows和Linux等多任务操作系统中,有多个程序在使用系统资源。需要为每个程序分配物理内存区域来在其中运行。可以设计这样一个操作系统:每个程序直接使用物理内存,并且可以可靠地仅使用分配给它的内存。一些嵌入式操作系统以这种方式工作,但是这在包含多个未经过集中测试的应用程序的环境中是不切实际的,因为任何程序都可能破坏其他程序或者操作系统本身的内存。虚拟内存允许多个进程共享物理内存,而且不会破坏彼此的数据。在具有虚拟内存的操作系统(比如Windows、Linux和许多其他操作系统)中,每个程序都拥有自己的虚拟地址空间——一个逻辑地址区域,其大小由该系统上的地址大小规定(所以,桌面和服务器平台的虚拟地址空间为31、32或64位)。进程的虚拟地址空间中的区域可被映射到物理内存、文件或任何其他可寻址存储。当数据未使用时,操作系统可以在物理内存与一个交换区域(Windows上的页面文件或者Linux上的交换分区)之间移动它,以实现对物理内存的最佳利用率。当一个程序尝试使用虚拟地址访问内存时,操作系统连同片上硬件会将该虚拟地址映射到物理位置,这个位置可以是物理RAM、一个文件或页面文件/交换分区。如果一个内存区域被移动到交换空间,那么它将在被使用之前加载回物理内存中。图1展示了虚拟内存如何将进程地址空间区域映射到共享资源:程序的每个实例以进程的形式运行。在Linux和Windows上,进程是一个由受操作系统控制的资源(比如文件和套接字信息)、一个典型的虚拟地址空间(在某些架构上不止一个)和至少一个执行线程构成的集合。虚拟地址空间大小可能比处理器的物理地址大小更小。32位Intelx86最初拥有的32位物理地址仅允许处理器寻址4GB存储空间。后来,添加了一种称为物理地址扩展(PhysicalAddressExtension,PAE)的特性,将物理地址大小扩大到了36位,允许安装或寻址至多64GBRAM。PAE允许操作系统将32位的4GB虚拟地址空间映射到一个较大的物理地址范围,但是它不允许每个进程拥有64GB虚拟地址空间。这意味着如果您将大于4GB的内存放入32位Intel服务器中,您将无法将所有内存直接映射到一个单一进程中。地址窗口扩展(AddressWindowingExtension)特性允许Windows进程将其32位地址空间的一部分作为滑动窗口映射到较大的内存区域中。Linux使用类似的技术将内存区域映射到虚拟地址空间中。这意味着尽管您无法直接引用大于4GB的内存,但您仍然可以使用较大的内存区域。内核空间和用户空间尽管每个进程都有其自己的地址空间,但程序通常无法使用所有这些空间。地址空间被划分为用户空间和内核空间。内核是主要的操作系统程序,包含用于连接计算机硬件、调度程序以及提供联网和虚拟内存等服务的逻辑。作为计算机启动序列的一部分,操作系统内核运行并初始化硬件。一旦内核配置了硬件及其自己的内部状态,第一个用户空间进程就会启动。如果用户程序需要来自操作系统的服务,它可以执行一种称为系统调用的操作与内核程序交互,内核程序然后执行该请求。系统调用通常是读取和写入文件、联网和启动新进程等操作所必需的。当执行系统调用时,内核需要访问其自己的内存和调用进程的内存。因为正在执行当前线程的处理器被配置为使用地址空间映射来为当前进程映射虚拟地址,所以大部分操作系统将每个进程地址空间的一部分映射到一个通用的内核内存区域。被映射来供内核使用的地址空间部分称为内核空间,其余部分称为用户空间,可供用户应用程序使用。内核空间和用户空间之间的平衡关系因操作系统的不同而不同,甚至在运行于不同硬件架构之上的同一操作系统的各个实例间也有所不同。这种平衡通常是可配置的,可进行调整来为用户应用程序或内核提供空间。缩减内核区域可能导致一些问题,比如能够同时登录的用户数量限制或能够运行的进程数量限制。更小的用户空间意味着应用程序编程人员只能使用更少的内存空间。默认情况下,32位Windows拥有2GB用户空间和2GB内核空间。在一些Windows版本上,通过向启动配置添加/3GB开关并使用/LARGEADDRESSAWARE开关重新链接应用程序,可以将这种平衡调整为3GB用户空间和1GB内核空间。在32位Linux上,默认设置为3GB用户空间和1GB内核空间。一些Linux分发版提供了一个hugemem内核,支持4GB用户空间。为了实现这种配置,将进行系统调用时使用的地址空间分配给内核。通过这种方式增加用户空间会减慢系统调用,因为每次进行系统调用时,操作系统必须在地址空间之间复制数据并重置进程地址-空间映射。图2展示了32位Windows的地址-空间布局:31位Linux390上还使用了一个独立的内核地址空间,其中较小的2GB地址空间使对单个地址空间进行划分不太合理,但是,390架构可以同时使用多个地址空间,而且不会降低性能。进程空间必须包含程序需要的所有内容,包括程序本身和它使用的共享库(在Windows上为DDL,在Linux上为.so文件)。共享库不仅会占据空间,使程序无法在其中存储数据,它们还会使地址空间碎片化,减少可作为连续内存块分配的内存。这对于在拥有3GB用户空间的Windowsx86上运行的程序尤为明显。DLL在构建时设置了首选的加载地址:当加载DLL时,它被映射到处于特定位置的地址空间,除非该位置已经被占用,在这种情况下,它会加载到别处。WindowsNT最初设计时设置了2GB可用用户空间,这对于要构建来加载接近2GB区域的系统库很有用——使大部分用户区域都可供应用程序自由使用。当用户区域扩展到3GB时,系统共享库仍然加载接近2GB数据(约为用户空间的一半)。尽管总体用户空间为3GB,但是不可能分配3GB大的内存块,因为共享库无法加载这么大的内存。在Windows中使用/3GB开关,可以将内核空间减少一半,也就是最初设计的大小。在一些情形下,可能耗尽1GB内核空间,使I/O变得缓慢,且无法正常创建新的用户会话。尽管/3GB开关可能对一些应用程序非常有用,但任何使用它的环境在部署之前都应该进行彻底的负载测试。参见参考资料,获取关于/3GB开关及其优缺点的信息的链接。本机内存泄漏或过度使用本机内存将导致不同的问题,具体取决于您是耗尽了地址空间还是用完了物理内存。耗尽地址空间通常只会发生在32位进程上,因为最大4GB的内存很容易分配完。64位进程具有数百或数千GB的用户空间,即使您特意消耗空间也很难耗尽这么大的空间。如果您确实耗尽了Java进程的地址空间,那么Java运行时可能会出现一些陌生现象,本文稍后将详细讨论。当在进程地址空间比物理内存大的系统上运行时,内存泄漏或过度使用本机内存会迫使操作系统交换后备存储器来用作本机进程的虚拟地址空间。访问经过交换的内存地址比读取驻留(在物理内存中)的地址慢得多,因为操作系统必须从硬盘驱动器拉取数据。可能会分配大量内存来用完所有物理内存和所有交换内存(页面空间),在Linux上,这将触发内核内存不足(OOM)结束程序,强制结束最消耗内存的进程。在Windows上,与地址空间被占满时一样,内存分配将会失败。同时,如果尝试使用比物理内存大的虚拟内存,显然在进程由于消耗内存太大而被结束之前就会遇到问题。系统将变得异常缓慢,因为它会将大部分时间用于在内存与交换空间之间来回复制数据。当发生这种情况时,计算机和独立应用程序的性能将变得非常糟糕,从而使用户意识到出现了问题。当JVM的Java堆被交换出来时,垃圾收集器的性能会变得非常差,应用程序可能被挂起。如果一台机器上同时使用了多个Java运行时,那么物理内存必须足够分配给所有Java堆。Java运行时如何使用本机内存Java运行时是一个操作系统进程,它会受到我在上一节中列出的硬件和操作系统局限性的限制。运行时环境提供的功能受一些未知的用户代码驱动,这使得无法预测在每种情形中运行时环境将需要何种资源。Java应用程序在托管Java环境中执行的每个操作都会潜在地影响提供该环境的运行时的需求。本节描述Java应用程序为什么和如何使用本机内存。Java堆和垃圾收集Java堆是分配了对象的内存区域。大多数JavaSE实现都拥有一个逻辑堆,但是一些专家级Java运行时拥有多个堆,比如实现Java实时规范(RealTimeSpecificationforJava,RTSJ)的运行时。一个物理堆可被划分为多个逻辑扇区,具体取决于用于管理堆内存的垃圾收集(GC)算法。这些扇区通常实现为连续的本机内存块,这些内存块受Java内存管理器(包含垃圾收集器)控制。堆的大小可以在Java命令行使用-Xmx和-Xms选项来控制(mx表示堆的最大大小,ms表示初始大小)。尽管逻辑堆(经常被使用的内存区域)可以根据堆上的对象数量和在GC上花费的时间而增大和缩小,但使用的本机内存大小保持不变,而且由-Xmx值(最大堆大小)指定。大部分GC算法依赖于被分配为连续的内存块的堆,因此不能在堆需要扩大时分配本机内存。所有堆内存必须预先保留。保留本机内存与分配本机内存不同。当本机内存被保留时,无法使用物理内存或其他存储器作为备用内存。尽管保留地址空间块不会耗尽物理资源,但会阻止内存被用于其他用途。由保留从未使用的内存导致的泄漏与泄漏分配的内存一样严重。当使用的堆区域缩小时,一些垃圾收集器会回收堆的一部分(释放堆的后备存储空间),从而减少使用的物理内存。对于维护Java堆的内存管理系统,需要本机内存来维护它的状态。当进行垃圾收集时,必须分配数据结构来跟踪空闲存储空间和记录进度。这些数据结构的确切大小和性质因实现的不同而不同,但许多数据结构都与堆大小成正比。即时(JIT)编译器JIT编译器在运行时编译Java字节码来优化本机可执行代码。这极大地提高了Java运行时的速度,并且支持Java应用程序以与本机代码相当的速度运行。字节码编译使用本机内存(使用方式与gcc等静态编译器使用内存来运行一样),但JIT编译器的输入(字节码)和输出(可执行代码)必须也存储在本机内存中。包含多个经过JIT编译的方法的Java应用程序会使用比小型应用程序的本机内存。类和类加载器Java应用程序由一些类组成,这些类定义对象结构和方法逻辑。Java应用程序也使用Java运行时类库(比如java.lang.String)中的类,也可以使用第三方库。这些类需要存储在内存中以备使用。存储类的方式取决于具体实现。SunJDK使用永久生成(permanentgeneration,PermGen)堆区域。Java5的IBM实现会为每个类加载器分配本机内存块,并将类数据存储在其中。现代Java运行时拥有类共享等技术,这些技术可能需要将共享内存区域映射到地址空间。要理解这些分配机制如何影响您Java运行时的本机内存占用,您需要查阅该实现的技术文档。然而,一些普遍的事实会影响所有实现。从最基本的层面来看,使用的类将需要使用内存。(这可能意味着您的本机内存使用量会增加,或者您必须明确地重新设置PermGen或共享类缓存等区域的大小,以装入所有类)。记住,不仅您的应用程序需要加载到内存中,框架、应用服务器、第三方库以及包含类的Java运行时也会按需加载并占用空间。Java运行时可以卸载类来回收空间,但是只有在非常严酷的条件下才会这样做。不能卸载单个类,而是卸载类加载器,随其加载的所有类都会被卸载。只有在以下情况下才能卸载类加载器:Java堆不包含对表示该类加载器的java.lang.ClassLoader对象的引用。Java堆不包含对表示类加载器加载的类的任何java.lang.Class对象的引用。在Java堆上,该类加载器加载的任何类的所有对象都不再存活(被引用)。需要注意的是,Java运行时为所有Java应用程序创建的3个默认类加载器(bootstrap、extension和application)都不可能满足这些条件,因此,任何系统类(比如java.lang.String)或通过应用程序类加载器加载的任何应用程序类都不能在运行时释放。即使类加载器适合进行收集,运行时也只会将收集类加载器作为GC周期的一部分。一些实现只会在某些GC周期中卸载类加载器。也可能在运行时生成类,而不用释放它。许多JEE应用程序使用JavaServerPages(JSP)技术来生成Web页面。使用JSP会为执行的每个.jsp页面生成一个类,并且这些类会在加载它们的类加载器的整个生存期中一直存在——这个生存期通常是Web应用程序的生存期。另一种生成类的常见方法是使用Java反射。反射的工作方式因Java实现的不同而不同,但Sun和IBM实现都使用了这种方法,我马上就会讲到。当使用java.lang.reflectAPI时,Java运行时必须将一个反射对象(比如java.lang.reflect.Field)的方法连接到被反射到的对象或类。这可以通过使用Java本机接口(JavaNativeInterface,JNI)访问器来完成,这种方法需要的设置很少,但是速度缓慢。也可以在运行时为您想要反射到的每种对象类型动态构建一个类。后一种方法在设置上更慢,但运行速度更快,非常适合于经常反射到一个特定类的应用程序。Java运行时在最初几次反射到一个类时使用JNI方法,但当使用了若干次JNI方法之后,访问器会膨胀为字节码访问器,这涉及到构建类并通过新的类加载器进行加载。执行多次反射可能导致创建了许多访问器类和类加载器。保持对反射对象的引用会导致这些类一直存活,并继续占用空间。因为创建字节码访问器非常缓慢,所以Java运行时可以缓存这些访问器以备以后使用。一些应用程序和框架还会缓存反射对象,这进一步增加了它们的本机内存占用。JNIJNI支持本机代码(使用C和C++等本机编译语言编写的应用程序)调用Java方法,反之亦然。Java运行时本身极大地依赖于JNI代码来实现类库功能,比如文件和网络I/O。JNI应用程序可能通过3种方式增加Java运行时的本机内存占用:JNI应用程序的本机代码被编译到共享库中,或编译为加载到进程地址空间中的可执行文件。大型本机应用程序可能仅仅加载就会占用大量进程地址空间。本机代码必须与Java运行时共享地址空间。任何本机代码分配或本机代码执行的内存映射都会耗用Java运行时的内存。某些JNI函数可能在它们的常规操作中使用本机内存。GetTypeArrayElements和GetTypeArrayRegion函数可以将Java堆数据复制到本机内存缓冲区中,以供本机代码使用。是否复制数据依赖于运行时实现。(IBMDeveloperKitforJava5.0和更高版本会进行本机复制)。通过这种方式访问大量Java堆数据可能会使用大量本机堆。
④ 如何优化java虚拟机,提高性能
关于性能调优:
1 需要一个性能探测器,找到调用最频繁的代码段,优化这部分代码(优化算法)
2 往往1%的代码运行时间占99%。所以优化这些代码就能事半功倍。
3 最好是能看懂编译后的代码,这样分析最彻底。
Java的性能分析使用JProfiler
堆栈分析使用的Jstack
Java性能调优 SSH框架优化以适应特定的项目
一、JVM调优
1 各种垃圾回收算法及其优劣;
2 针对不同应用类型如何选择JVM参数
3 常用调优工具的使用(jps/jstat/jmap/jstack/jinfo/jhat)
4 调优案例分析(如何选择不同内存块的大小,如何选择不同的算法来提升性能、响应时间)
二、Java应用中CPU占用率、使用情况分析,线程死锁等锁
系统性能瓶颈的分析定位
1 JStack的深度使用
2 各种Linux监控命令的配合使用(top,vmstat,iostat,sar 不要轻信自己能完全掌控这些命令)、分析
(前一阵Java漏洞通过制造Hash冲突来占尽CPU资源就可以通过top命令快速定位到,你肯定没有这么用过)
3 JProfiler的详细使用
三、Java内存溢出分析
1 用EMA来分析内存占用情况
2 通过案例分析来定位内存泄漏
互联网中的性能主要是两个方面:
1 吞吐量,就是系统支持的访问量。
2 延迟,就是一个请求提交后,相应的时间。
一般硬件不变的情况下,两方面各自优化到极限后,相互会制约,也就是吞吐量增强的话比如需要延迟加大,反之亦然。
⑤ 如何在linux下检测内存泄漏
内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。
可以使用相应的软件测试工具对软件进行检测。
1. ccmalloc-Linux和Solaris下对C和C++程序的简单的使用内存泄漏和malloc调试库。
2. Dmalloc-Debug Malloc Library.
3. Electric
Fence-Linux分发版中由Bruce Perens编写的malloc()调试库。
4. Leaky-Linux下检测内存泄漏的程序。
5. LeakTracer-Linux、Solaris和HP-UX下跟踪和分析C++程序中的内存泄漏。
6. MEMWATCH-由Johan
Lindh编写,是一个开放源代码C语言内存错误检测工具,主要是通过gcc的precessor来进行。
7. Valgrind-Debugging and profiling Linux programs, aiming at
programs written in C and C++.
8. KCachegrind-A visualization tool for the profiling data
generated by Cachegrind and Calltree.
9. Leak
Monitor-一个Firefox扩展,能找出跟Firefox相关的泄漏类型。
10. IE Leak Detector
(Drip/IE Sieve)-Drip和IE Sieve leak
detectors帮助网页开发员提升动态网页性能通过报告可避免的因为IE局限的内存泄漏。
11. Windows Leaks
Detector-探测任何Win32应用程序中的任何资源泄漏(内存,句柄等),基于Win API调用钩子。
12. SAP Memory
Analyzer-是一款开源的JAVA内存分析软件,可用于辅助查找JAVA程序的内存泄漏,能容易找到大块内存并验证谁在一直占用它,它是基于Eclipse
RCP(Rich Client Platform),可以下载RCP的独立版本或者Eclipse的插件。
13. DTrace-即动态跟踪Dynamic
Tracing,是一款开源软件,能在Unix类似平台运行,用户能够动态检测操作系统内核和用户进程,以更精确地掌握系统的资源使用状况,提高系统性能,减少支持成本,并进行有效的调节。
14. IBM Rational PurifyPlus-帮助开发人员查明C/C++、托管.NET、Java和VB6代码中的性能和可靠性错误。PurifyPlus
将内存错误和泄漏检测、应用程序性能描述、代码覆盖分析等功能组合在一个单一、完整的工具包中。
15. Parasoft Insure++-针对C/C++应用的运行时错误自动检测工具,它能够自动监测C/C++程序,发现其中存在着的内存破坏、内存泄漏、指针错误和I/O等错误。并通过使用一系列独特的技术(SCI技术和变异测试等),彻底的检查和测试我们的代码,精确定位错误的准确位置并给出详细的诊断信息。能作为Microsoft
Visual C++的一个插件运行。
16. Compuware DevPartner for Visual C++ BoundsChecker
Suite-为C++开发者设计的运行错误检测和调试工具软件。作为Microsoft Visual Studio和C++ 6.0的一个插件运行。
17. Electric Software GlowCode-包括内存泄漏检查,code
profiler,函数调用跟踪等功能。给C++和.Net开发者提供完整的错误诊断,和运行时性能分析工具包。
18. Compuware DevPartner Java
Edition-包含Java内存检测,代码覆盖率测试,代码性能测试,线程死锁,分布式应用等几大功能模块。
19. Quest JProbe-分析Java的内存泄漏。
20. ej-technologies JProfiler-一个全功能的Java剖析工具,专用于分析J2SE和J2EE应用程序。它把CPU、执行绪和内存的剖析组合在一个强大的应用中。JProfiler可提供许多IDE整合和应用服务器整合用途。JProfiler直觉式的GUI让你可以找到效能瓶颈、抓出内存泄漏、并解决执行绪的问题。4.3.2注册码:A-G666#76114F-1olm9mv1i5uuly#0126
21. BEA JRockit-用来诊断Java内存泄漏并指出根本原因,专门针对Intel平台并得到优化,能在Intel硬件上获得最高的性能。
22. SciTech Software AB .NET Memory
Profiler-找到内存泄漏并优化内存使用针对C#,VB.Net,或其它.Net程序。
23. YourKit .NET & Java Profiler-业界领先的Java和.NET程序性能分析工具。
24. AutomatedQA AQTime-AutomatedQA的获奖产品performance profiling和memory
debugging工具集的下一代替换产品,支持Microsoft, Borland, Intel, Compaq 和
GNU编译器。可以为.NET和Windows程序生成全面细致的报告,从而帮助您轻松隔离并排除代码中含有的性能问题和内存/资源泄露问题。支持.Net
1.0,1.1,2.0,3.0和Windows 32/64位应用程序。
25. JavaScript Memory Leak Detector-微软全球产品开发欧洲团队(Global Proct
Development- Europe team, GPDE)
发布的一款调试工具,用来探测JavaScript代码中的内存泄漏,运行为IE系列的一个插件。
⑥ 如何使用JProfiler查找内存泄漏
先运行的java程序,然后打开jprofiler,绑定正在运行的程序,就可以在界面看到内存的使用情况。
⑦ 请问什么叫java内存泄露
上面的已经介绍得很清楚了,简单点说就是java没有释放用过的内存,继续在系统内存中占用!