精华内容
下载资源
问答
  • JVM 内存优化

    2011-09-28 14:17:20
    淘宝林昊总结的JVM优化问题,比他写的那本书讲的更深入些
  • 认识JVM内存优化, 避免最大的误区:认为JVM内存越大越好。看到一个线程 blocked就认为阻塞了。
  • Linux环境的Tomcat JVM内存优化 java虚拟机内存溢出问题的解决
  • CentOS 7 Linux 安装Tomcat 8 - JVM内存优化(咋个办呢 zgbn) 参考:CentOS 7 Linux 安装Tomcat 8 配置Tomcat启动JVM时分配的内存 JVM内存分配默认情况说明 JAVA_OPTS="-server -Xms2048m -Xmx2048m -XX:...

    CentOS 7 Linux 安装Tomcat 8 - JVM内存优化(咋个办呢 zgbn)

    参考:CentOS 7 Linux 安装Tomcat 8

    配置Tomcat启动JVM时分配的内存

    JVM内存分配默认情况说明

    JAVA_OPTS="-server -Xms2048m -Xmx2048m -XX:PermSize=128M -XX:MaxPermSize=128m"

    JVM内存配置参数 描述
    -Xmx Java Heap最大值,默认值为物理内存的1/4;
    -Xms Java Heap初始值,Server端JVM最好将-Xms和-Xmx设为相同值,开发测试机JVM可以保留默认值;
    -Xmn Java Heap Young区大小,不熟悉最好保留默认值;
    -XX:PermSize
    展开全文
  • linux tomcat jvm内存优化

    千次阅读 2012-10-25 11:03:55
    linux tomcat jvm内存优化  2011-06-29 11:55:08| 分类: tomcat | 标签:tomcat jvm  |字号 订阅 PermGen space:全称是Permanent Generation space。就是说是永久保存的区域,用于存放Class...

    linux tomcat jvm内存优化  

    2011-06-29 11:55:08|  分类: tomcat |  标签:tomcat  jvm   |字号 订阅

    PermGen space:全称是Permanent Generation space。就是说是永久保存的区域,用于存放Class和Meta信息,Class在被Load的时候被放入该区域
    Heap space:存放Instance。

    GC(Garbage Collection)应该不会对PermGen space进行清理
    所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误

    Java Heap分为3个区,Young,Old和Permanent。Young保存刚实例化的对象。当该区被填满时,GC会将对象移到Old区。Permanent区则负责保存反射对象,本文不讨论该区。


    JVM的Heap分配可以使用-X参数设定,


    -Xms

    初始Heap大小

    -Xmx

    java heap最大值

    -Xmn

    young generation的heap大小



    JVM有2个GC线程。第一个线程负责回收Heap的Young区。第二个线程在Heap不足时,遍历Heap,将Young 区升级为Older区。Older区的大小等于-Xmx减去-Xmn,不能将-Xms的值设的过大,因为第二个线程被迫运行会降低JVM的性能。
    为什么一些程序频繁发生GC?有如下原因:
    l         程序内调用了System.gc()或Runtime.gc()。
    l         一些中间件软件调用自己的GC方法,此时需要设置参数禁止这些GC。
    l         Java的Heap太小,一般默认的Heap值都很小。
    l         频繁实例化对象,Release对象。此时尽量保存并重用对象,例如使用StringBuffer()和String()。
    如果你发现每次GC后,Heap的剩余空间会是总空间的50%,这表示你的Heap处于健康状态。许多Server端的Java程序每次GC后最好能有65%的剩余空间。
    经验之谈:
    1ServerJVM最好将-Xms-Xmx设为相同值。为了优化GC,最好让-Xmn值约等于-Xmx1/3[2]
    2.一个GUI程序最好是每1020秒间运行一次GC,每次在半秒之内完成[2]

    注意:
    1.增加Heap的大小虽然会降低GC的频率,但也增加了每次GC的时间。并且GC运行时,所有的用户线程将暂停,也就是GC期间,Java应用程序不做任何工作。
    2.Heap大小并不决定进程的内存使用量。进程的内存使用量要大于-Xmx定义的值,因为Java为其他任务分配内存,例如每个线程的Stack等。


    Stack的设定
    每个线程都有他自己的Stack。


    -Xss

    每个线程的Stack大小



    Stack的大小限制着线程的数量。如果Stack过大就好导致内存溢漏。-Xss参数决定Stack大小,例如-Xss1024K。如果Stack太小,也会导致Stack溢漏。


    关于maxMemory(),freeMemory()和totalMemory(): 


    maxMemory()为JVM的最大可用内存,可通过-Xmx设置,默认值为物理内存的1/4,设值不能高于计算机物理内存; 


    totalMemory()为当前JVM占用的内存总数,其值相当于当前JVM已使用的内存及freeMemory()的总和,会随着JVM使用内存的增加而增加; 


    freeMemory()为当前JVM空闲内存,因为JVM只有在需要内存时才占用物理内存使用,所以freeMemory()的值一般情况下都很小,而JVM实际可用内存并不等于freeMemory(),而应该等于maxMemory()-totalMemory()+freeMemory()。及其设置JVM内存分配




    设置JVM内存的参数有四个: 


    -Xmx    Java Heap最大值,默认值为物理内存的1/4,最佳设值应该视物理内存大小及计算机内其他内存开销而定; 


    -Xms    Java Heap初始值,Server端JVM最好将-Xms和-Xmx设为相同值,开发测试机JVM可以保留默认值; 


    -Xmn    Java Heap Young区大小,不熟悉最好保留默认值; 


    -Xss    每个线程的Stack大小,不熟悉最好保留默认值; 




    在JVM中如果98%的时间是用于GC且可用的 Heap size 不足2%的时候将抛出此异常信息。 

    JVM堆的设置是指java程序运行过程中JVM可以调配使用的内存空间的设置.JVM在启动的时候会自动设置Heap size的值,其初始空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置。




    另外需要考虑的是Java提供的垃圾回收机制。虚拟机的堆大小决定了虚拟机花费在收集垃圾上的时间和频度。收集垃圾可以接受的速度与应用有关,应该通过分析实际的垃圾收集的时间和频率来调整。如果堆的大小很大,那么完全垃圾收集就会很慢,但是频度会降低。如果你把堆的大小和内存的需要一致,完全收集就很快,但是会更加频繁。调整堆大小的的目的是最小化垃圾收集的时间,以在特定的时间内最大化处理客户的请求。在基准测试的时候,为保证最好的性能,要把堆的大小设大,保证垃圾收集不在整个基准测试的过程中出现。


    如果系统花费很多的时间收集垃圾,请减小堆大小。一次完全的垃圾收集应该不超过3-5秒。如果垃圾收集成为瓶颈,那么需要指定代的大小,检查垃圾收集的详细输出,研究垃圾收集参数对性能的影响。一般说来,你应该使用物理内存的80%作为堆大小。当增加处理器时,记得增加内存,因为分配可以并行进行,而垃圾收集不是并行的。


    一个要注意的地方:建议把内存的最高值跟最低值的差值缩小,不然会浪费很多内存的,最低值加大,最高值可以随便设,但是要根据实际的物理内存,如果内存设置太大了,比如设置了512M最大内存,但如果没有512M可用内存,Tomcat就不能启动,还有可能存在内存被系统回收,终止进程的情况




    如何设置Tomcat的JVM内存大小


    Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个JVM。JAVA程序启动时JVM都会分配一个初始JVM内存和最大JVM内存给这个应用程序。这个初始内存和最大内存在一定程度都会影响程序的性能。比如说在应用程序用到最大内存的时候,JVM是要先去做垃圾回收的动作,释放被占用的一些内存。所以想调整Tomcat的启动时初始内存和最大内存就需要向JVM声明,一般的JAVA程序在运行都可以通过中-Xms-Xmx来调整应用程序的初始内存和最大内存:


    这两个值的大小一般根据需要进行设置。初始化堆的大小执行了虚拟机在启动时向系统申请的内存的大小。一般而言,这个参数不重要。但是有的应用程序在大负载的情况下会急剧地占用更多的内存,此时这个参数就是显得非常重要,如果虚拟机启动时设置使用的内存比较小而在这种情况下有许多对象进行初始化,虚拟机就必须重复地增加内存来满足使用。由于这种原因,我们一般把-Xms和-Xmx设为一样大,而堆的最大值受限于系统使用的物理内存。一般使用数据量较大的应用程序会使用持久对象,内存使用有可能迅速地增长。当应用程序需要的内存超出堆的最大值时虚拟机就会提示内存溢出,并且导致应用服务崩溃。因此一般建议堆的最大值设置为可用JVM内存的最大值的80%。


    Tomcat默认可以使用的内存为128MB,在较大型的应用项目中,这点内存是不够的,需要调大。有以下几种方法可以选用:


    第一种方法:


    Windows下,在文件/bin/catalina.bat,Unix下,在文件/bin/catalina.sh的前面,增加如下设置:


    JAVA_OPTS='-Xms【初始化内存大小】-Xmx【可以使用的最大内存】'


    需要把这个两个参数值调大。例如:


    JAVA_OPTS='-Xms256m-Xmx512m'


    表示初始化内存为256MB,可以使用的最大内存为512MB。


    第二种方法:环境变量中设


    变量名:JAVA_OPTS


    变量值:-Xms512m-Xmx512m


    第三种方法:前两种方法针对的是bin目录下有catalina.bat的情况(比如直接解压的Tomcat等),但是有些安装版的Tomcat下没有catalina.bat,这个时候可以采用如下方法,当然这个方法也是最通用的方法:


    打开tomcatHome/\bin/\tomcat5w.exe,点击Java选项卡,然后将会发现其中有这么两项:Initialmemorypool和Maximummemorypool.Initialmemorypool这个就是初始化设置的内存的大小。Maximummemorypool这个是最大JVM内存的大小设置完了就按确定然后再重启TOMCAT你就会发现tomcat中jvm可用的内存改变了。




    第三种:无法创建新的线程。


      这种现象比较少见,也比较奇怪,主要是和jvm与系统内存的比例有关。


      这种怪事是因为JVM已经被系统分配了大量的内存(比如1.5G),并且它至少要占用可用内存的一半。有人发现,在线程个数很多的情况下,你分配给JVM的内存越多,那么,上述错误发生的可能性就越大。


      产生这种现象的原因如下(从这个blog中了解到原因:http://hi.baidu.com/hexiong/blog ... b10c2542a75b3c.html):        每一个32位的进程最多可以使用2G的可用内存,因为另外2G被操作系统保留。这里假设使用1.5G给JVM,那么还余下500M可用内存。这500M内存中的一部分必须用于系统dll的加载,那么真正剩下的也许只有400M,现在关键的地方出现了:当你使用Java创建一个线程,在JVM的内存里也会创建一个Thread对象,但是同时也会在操作系统里创建一个真正的物理线程(参考JVM规范),操作系统会在余下的400兆内存里创建这个物理线程,而不是在JVM的1500M的内存堆里创建。在jdk1.4里头,默认的栈大小是256KB,但是在jdk1.5里头,默认的栈大小为1M每线程,因此,在余下400M的可用内存里边我们最多也只能创建400个可用线程。


      这样结论就出来了,要想创建更多的线程,你必须减少分配给JVM的最大内存。还有一种做法是让JVM宿主在你的JNI代码里边。


      给出一个有关能够创建线程的最大个数的估算公式:


      (MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads


      对于jdk1.5而言,假设操作系统保留120M内存:


      1.5GB JVM: (2GB-1.5Gb-120MB)/(1MB) = ~380 threads


      1.0GB JVM: (2GB-1.0Gb-120MB)/(1MB) = ~880 threads


      在2000/XP/2003的boot.ini里头有一个启动选项,好像是:/PAE /3G ,可以让用户进程最大内存扩充至3G,这时操作系统只能占用最多1G的虚存。那样应该可以让JVM创建更多的线程。


      因此这种情况需要结合操作系统进行相关调整。


      因此:我们需要结合不同情况对tomcat内存分配进行不同的诊断才能从根本上解决问题。




     编辑tomcat的catalina.sh文件,在第一行的后面增加一句: 

    JAVA_OPTS='-server -Xms256m -Xmx512m -XX:PermSize=128M -XX:MaxPermSize=256M' 

    注意:单引号不能少,-server表示以server模式运行(运行效率比默认的client高很多,自己云去测试),-Xms256m是最小内存,-Xmx512m是最大内存,其中的256与512可根据你自己的内存做相应调整,PermSize/MaxPermSize最小/最大堆大小.一般报内存不足时,都是说这个太小,堆空间剩余小于5%就会警告,建议把这个稍微设大一点,不过要视自己机器内存大小来设置,我自己的文件如下: 

    #!/bin/sh 

    JAVA_OPTS='-server -Xms1024m -Xmx1024m XX:PermSize=128M -XX:MaxPermSize=256M' 




    . 各个参数的含义什么? 


    参数中-vmargs的意思是设置JVM参数,所以后面的其实都是JVM的参数了,我们首先了解一下JVM内存管理的机制,然后再解释每个参数代表的含义。 


    ◆堆(Heap)和非堆(Non-heap)内存 


    按照官方的说法:“Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。”“在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。可以看出JVM主要管理两种类型的内存:堆和非堆。简单来说堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给自己用的,所以方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中。 


    ◆堆内存分配 


    JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。因此服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小。 


    ◆非堆内存分配 


    JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。 


    ◆JVM内存限制(最大值) 


    首先JVM内存限制于实际的最大物理内存(废话!呵呵),假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系。简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制了。


    转自:http://blog.163.com/agw_slsyn/blog/static/30915112201152911558409/


    展开全文
  • JVM内存优化——小试牛刀

    千次阅读 2016-09-09 01:59:14
    最近在拜读周志明的《深入理解Java虚拟机》,看了Java的内存管理机制以及Jvm优化相关内容。于是,下载了sun提供的Jvm检测工具VisualVm。下载地址:https://visualvm.java.net/ 安装就很简单了,在此略过。 一、启动...

        最近在拜读周志明的《深入理解Java虚拟机》,看了Java的内存管理机制以及Jvm优化相关内容。于是,下载了sun提供的Jvm检测工具VisualVm。

    VisualVm下载地址:https://visualvm.java.net/
    安装就很简单了,在此略过。
    作者博客地址:http://icyfenix.iteye.com/
    可以下载PDF版的《Java虚拟机规范 (Java SE 7 中文版)》
    

    一、启动程序


    1. 查看系统中运行的Java进程

    左侧显示当前系统中运行的虚拟机进程,双击连接后可以监测虚拟机的运行状况。
    这里写图片描述

    2. 安装VisualGC插件

    工具栏中“工具”→“插件”
    这里写图片描述

    由于我已经安装过了,如果没有安装,目录中会有VisualGC。该工具可以查看不同内存区域的使用情况和GC情况,效果如图

    这里写图片描述


    二、问题描述

    使用jps命令,可以查看系统中运行的jvm进程

    $ jps
    2064 TestMain
    1389 Main
    2267 Jps
    1009
    287

    忽然发现个奇特的东西,就是TestMain进程,这个名字好奇怪,不是我创建的,在“活动监视器”中搜了一下PID,发现是公司的Hosts管理工具。奇怪的是,一款小小的Hosts管理工具竟然使用了将近1.5G的内存,吓死宝宝了。

    于是反应给工具维护人员,很快进行了优化,释放了无用内存。但是总的内存占用量仍然有700+M,在切换几次环境之后,会稳定到这个值。因为我在公共配置里添加了Google的Hosts内容,所有触发了这个问题。

    这个内存占用量,是特别的高,显然不是开发人员设定的值,而是OS X Java Plugin的默认设置。这种工具,内存占用应该只是在100M以下,最后能做20-30M最好。


    三、使用VisualVM监视工具内存使用情况

    这里写图片描述

    十分钟的内存使用情况:
    这里写图片描述

    在1处,切换了环境,可见同事优化的地方正在此,在切换环境的时候释放了内存,触发了Eden区的GC。

    但在这之前,将近十分钟,内存使用量在稳步上升,竟然一次都没有触发GC,这就很奇怪了。应该是内存空间足够有关,程序刚开始运行,竟然就申请了1200+M的内存,真不知道系统咋想的。这和OS X JRE运行环境有关,应该是使用的默认的对内存大小限制。但是就目前的程序而言,显然这么多的内存有些浪费。


    四、堆内存优化过程


    1. 优化堆内存大小

    从曲线中可以看出来,堆内存的使用量最大也没超过200M,所以限定一下最大堆内存为200M,使用如下参数:

    -Xmx200m

    但是Mac系统的虚拟机参数在哪里设置呢?
    这里写图片描述

    打开应用程序的目录,可以看见Info.plist文件,程序的启动参数就在这里面设置的,找到如下节点,添加堆内存最大限制-Xmx参数:

        <key>JVMOptions</key>
        <array>
              <string>-Dapple.laf.useScreenMenuBar=true</string>
              <string>-Xdock:name=HostsManager</string>
              <string>-Xmx200m</string>
        </array>

    所有在OS X下的Java Application都可以在该文件中设置虚拟机参数。

    2. 初次优化堆内存

    观察堆内存情况,如下图所示:

    这里写图片描述

    自动触发了GC操作之前,内存使用量快并未达到60M。所有200M还是比较多余的,大概4分钟触发一次GC,回收了内存。
    可以试试将堆内存最大设置为80M,看看情况,会不会发生堆内存溢出。修改Info.plist

        <key>JVMOptions</key>
        <array>
              <string>-Dapple.laf.useScreenMenuBar=true</string>
              <string>-Xdock:name=HostsManager</string>
              <string>-Xmx80m</string>
        </array>


    2. 再次优化堆内存

    从堆内存使用数据来看,在内存到25M作用时,就主动触发了GC,回收了内存,可见,应用程序真正使用的内存还不到30M,堆内存最大使用率还不足25%,实在浪费。如图所示:
    这里写图片描述

    最大堆内存,这次设置为40M,在观察一下效果:

    3. 第三次优化堆内存使用

    这里写图片描述

    这下堆内存的使用率能够达到一半以上了,最大40M,基本达到了预期效果。进一步压缩堆内存,还能进一步优化,会更加频繁的触发GC操作。

    这里写图片描述

    这里写图片描述

    注意两幅图,截取的时间长度不同,所有不是GC越频繁,而是达到一定的内存的值,触发的GC操作。

    最终设置堆内存大小为30M,总的内存使用量为110M作用,达到初期优化目标。



    五、总体内存优化

    这时候,该使用我们按的差距VisualGC了,看一下总体的内存使用情况:

    这里写图片描述

    前面我们已经优化了堆内存,所有堆内存区域的数据还是比较理想的。使用VisualGC插件,内存使用情况更加清晰,优化目标也更明确。

    数据说明:
    Space:内存使用情况,实线格子是已经申请的内存,有颜色的部分是已使用内存,总体是内存区域的最大值。
    Perm:永久代
    Old:老年代
    S0、S1、Eden: 新生代
    老年代和新生代都属于Java堆内存(Heap),即-Xmx限制的区域。

    最大内存:82+20+3+3+9 = 117M,接近于系统“活动监视器”中显示的内存值114.5M

    Graphs:
    Compile Time: 352 compiles 2.960s
        运行时编译时间,对热点代码(HotSpot JDK默认虚拟机的名称由来),将字节码编译成本地二进制,编译了352次,共使用时间2.960s

    Class Loader Time:
        类加载时间,加载了2946个类,共花费719.913ms,有1个类未加载。

    Eden Space (9.000M, 4.000M):3.444M 959 collections, 849.736ms。
        9.000M 该区域最大内存,4.000M当前已经申请的内存,3.444M已经使用的内存,变化很快。也是GC最频繁的区域,幸存的对象,移入S0或者S1区域。该区域的GC为Moni GC,最频繁,也是速度最快的。老年代内存满了,会触发Full GC,会暂停所有用户进程值安全点,进行GC,速度比较慢。具体不在赘述,放JVM内存管理中详细叙述。
    其他内存区域参数同理。

        可以看到,新生代和老年代的使用率已经没有太大的空间可以优化了,但是永久代的内存82M,才使用了17M,使用率不足35%,可以大刀阔斧的,将其最大值设置为25M,六点余地,以免不够用。虽然才申请了21M,但是剩下的61M,也是化为了私有内存的,其他进程也是无法使用的。

    最终优化参数如下:

        <key>JVMOptions</key>
        <array>
              <string>-Dapple.laf.useScreenMenuBar=true</string> <!-- 菜单配置 -->
              <string>-Xdock:name=HostsManager</string> <!-- dock显示名称 -->
              <string>-Xmx30m</string> <!-- 最大堆内存 -->
              <string>-Xms30m</string> <!-- 最小堆内存 -->
              <string>-Xmn10m</string> <!-- 堆内存块单元大小 -->
              <string>-XX:PermSize=25m</string> <!-- 初始永久代大小 -->
              <string>-XX:MaxPermSize=25m</string><!-- 永久代最大值 -->
        </array>


    最终,总的内存消耗,如图:
    这里写图片描述

    jvm内存详情:

    这里写图片描述

        可以看出来,内存总体使用情况还是可以进一步优化,但是空间并不大,也没这个必要了。优化完成后,总消耗内存控制在70M左右。基本达成目标。

    PS:Java应用记得设置内存参数哦,OS X系统默认是个坑!

    展开全文
  • CentOS 7 Linux 安装Tomcat 8 - JVM内存优化

    千次阅读 2018-07-16 19:58:45
    JVM内存分配默认情况说明 JAVA_OPTS="-server -Xms2048m -Xmx2048m -XX:PermSize=128M -XX:MaxPermSize=128m" JVM内存配置参数 描述 -Xmx Java Heap最大值,默认值为物理内存的1/4; -Xms ...

    配置Tomcat启动JVM时分配的内存

    JVM内存分配默认情况说明

    JAVA_OPTS="-server -Xms2048m -Xmx2048m -XX:PermSize=128M -XX:MaxPermSize=128m"

    JVM内存配置参数描述
    -XmxJava Heap最大值,默认值为物理内存的1/4;
    -XmsJava Heap初始值,Server端JVM最好将-Xms和-Xmx设为相同值,开发测试机JVM可以保留默认值;
    -XmnJava Heap Young区大小,不熟悉最好保留默认值;
    -XX:PermSize设定内存的永久保存区域;
    -XX:MaxPermSize设定最大内存的永久保存区域;
    -XX:NewSize设置JVM堆的新生代的默认大小;
    -XX:MaxNewSize设置JVM堆的新生代的最大大小;
    -Xss每个线程的Stack大小,不熟悉最好保留默认值;

    JVM堆内存分配

    -Xms约定了JVM启动是初始化分配物理内存,默认为物理内存的1/64; 
    -Xmx约定了JVM运行时最大分配的物理内存,默认是物理内存的1/4;

    在JVM运行时,当JVM空闲堆内存大于自身占用内存的70%时,JVM就会自动释放对内存一直达到-Xms约定的最小值,JVM调整自身堆内存时通常是在GC后发生。


    内存优化 
    - 所以我们可以手动去设置-Xms-Xmx相等,避免在每次GC 后调整堆的大小。 
    - 建议堆内存的最大值设置-Xmx为可用内存的最大值的80%。 


    内存溢出 
    -Xms<-Xmx时,JVM启动失败; 
    -Xmx> 可用物理内存时,JVM启动失败; 
    - 应用程序在启动和运行时所使用的内存超出-Xmx时,JVM发生内存溢出( OutOfMemoryError: Java heap space); 

    JVM非堆内存分配

    -XX:PermSize设置非堆内存初始值,默认是物理内存的1/64; 
    -XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4;

    JVM非堆内存(永久内存区),用于存放Class和Meta信息,应用程序所有的Class在被JVM加载的时候被放入该区域。它和存放类实例(Instance)的堆区域(Heap)不同,垃圾回收GC(Garbage Collection)不会在主程序运行期对非堆内存区(PermGen space)进行清理。 

    内存优化 
    - 建议根据服务器部署应用程序的实际情况分配,可以通过jconsole工具观察一下JVM启动后内存的使用情况进而分配; 
    - 建议将-XX:PermSize-XX:MaxPermSize值设置为相等。 


    内存溢出 
    - JVM启动加载应用程序时,加载class所使用内存超出-XX:MaxPermSize,则发生非堆内存溢出错误(OutOfMemoryError: PermGen space); 
    - 当-Xmx+-XX:MaxPermSize两者设置的内存超出系统可用物理内存时,JVM启动失败; 

    JVM内存的异常错误

    感谢参考:http://blog.csdn.net/thunder0709/article/details/16855195

    OutOfMemoryError: Java heap space

    内存溢出主要存在问题就是出现在这个情况中。当在JVM中如果98%的时间是用于GC且可用的 Heap size 不足2%的时候将抛出此异常信息。

    OutOfMemoryError: PermGen space

    这种错误常见在web服务器对JSP进行pre compile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小,那么就会产生此错误信息了。如果web app用了大量的第三方jar或者应用有太多的class文件而恰好MaxPermSize设置较小,超出了也会导致这块内存的占用过多造成溢出,或者tomcat热部署时侯不会清理前面加载的环境,只会将context更改为新部署的,非堆存的内容就会越来越多。

    OutOfMemoryError: unable to create new native thread

    这种现象比较少见,也比较奇怪,主要是和jvm与系统内存的比例有关。这种怪事是因为JVM已经被系统分配了大量的内存(比如1.5G),并且它至少要占用可用内存的一半。

    查看JVM内存信息

    使用jconsole工具查看JVM运行时内存

    window系统安装JDK包中,有自带的jconsole工具,可以通过jconsole工具链接远程服务器的JVM实例,查看JVM运行时的内存。 
    顺便介绍另一个JDK自带的工具jvisualvm,可以使用此工具对JAVA程序进行性能测试,分析程序性能数据等等(具体用法大家自行百度一下)。 
    顺便介绍另一个JDK自带的工具jmc,可以使用此工具远程监控JVM,运行此工具后主界面有对此工具的介绍”Oracle Java Mission Control 是什么?”。

    位置:%JAVA_HOME%/bin/jconsole.exe 
    位置:%JAVA_HOME%/bin/jvisualvm.exe 
    位置:%JAVA_HOME%/bin/jmc.exe

    使用JAVA程序查看JVM运行时内存

    //最大可用内存,对应-Xmx 
    Runtime.getRuntime().maxMemory(); 
    //当前JVM空闲内存 
    Runtime.getRuntime().freeMemory(); 
    //当前JVM占用的内存总数,其值相当于当前JVM已使用的内存及freeMemory()的总和
    Runtime.getRuntime().totalMemory(); 

    配置Tomcat以catalina.sh启动配置JVM内存

    综上,已经说明JVM内存的一些注意事情,下面直接描述一下Tomcat通过catalina.sh启动配置JVM内存分配的方法。

    备注:以catalina.sh方式启动Tomcat的方法【点击查看】

    进入%TOMCAT_HOME%/bin目录下,找到catalina.sh脚本。 
    1、测试一下catalina.sh启动服务是否正常。 
    执行下面命令,可以看一下Tomcat一些启动信息。

    [root@iZ28snxdn5mZ bin]# ./catalina.sh start
    Using CATALINA_BASE:   /opt/apache/tomcat-8
    Using CATALINA_HOME:   /opt/apache/tomcat-8
    Using CATALINA_TMPDIR: /opt/apache/tomcat-8/temp
    Using JRE_HOME:        /usr
    Using CLASSPATH:       /opt/apache/tomcat-8/bin/bootstrap.jar:/opt/apache/tomcat-8/bin/tomcat-juli.jar
    Tomcat started.
    
    [root@iZ28snxdn5mZ bin]# ./catalina.sh stop

    2、使用vim编辑器打开catalina.sh脚本。在该脚本执行语句之前追加下面代码。

    JAVA_OPTS="-server -Xms896m -Xmx896m -XX:PermSize=128M -XX:MaxPermSize=128m"
    • 1

    这里写图片描述 
    然后重新执行脚本启动Tomcat服务。

    [root@iZ28snxdn5mZ bin]# ./catalina.sh start
    Using CATALINA_BASE:   /opt/apache/tomcat-8
    Using CATALINA_HOME:   /opt/apache/tomcat-8
    Using CATALINA_TMPDIR: /opt/apache/tomcat-8/temp
    Using JRE_HOME:        /usr
    Using CLASSPATH:       /opt/apache/tomcat-8/bin/bootstrap.jar:/opt/apache/tomcat-8/bin/tomcat-juli.jar
    Tomcat started.
    
    [root@iZ28snxdn5mZ bin]# ps -ef | grep tomcat
    root     23795     1  3 20:06 pts/0    00:00:01 /usr/bin/java -Djava.util.logging.config.file=/opt/apache/tomcat-8/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -server -Xms896m -Xmx896m -XX:PermSize=128M -XX:MaxPermSize=128m -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dignore.endorsed.dirs= -classpath /opt/apache/tomcat-8/bin/bootstrap.jar:/opt/apache/tomcat-8/bin/tomcat-juli.jar -Dcatalina.base=/opt/apache/tomcat-8 -Dcatalina.home=/opt/apache/tomcat-8 -Djava.io.tmpdir=/opt/apache/tomcat-8/temp org.apache.catalina.startup.Bootstrap start
    root     23838 23179  0 20:06 pts/0    00:00:00 grep --color=auto tomcat
    
    [root@iZ28snxdn5mZ bin]# ./catalina.sh stop
    Using CATALINA_BASE:   /opt/apache/tomcat-8
    Using CATALINA_HOME:   /opt/apache/tomcat-8
    Using CATALINA_TMPDIR: /opt/apache/tomcat-8/temp
    Using JRE_HOME:        /usr
    Using CLASSPATH:       /opt/apache/tomcat-8/bin/bootstrap.jar:/opt/apache/tomcat-8/bin/tomcat-juli.jar
    OpenJDK 64-Bit Server VM warning: ignoring option PermSize=128M; support was removed in 8.0
    OpenJDK 64-Bit Server VM warning: ignoring option MaxPermSize=128m; support was removed in 8.0
    [root@iZ28snxdn5mZ bin]#

    备注:在执行./catalina.sh stop后,日志提示我们下面两句话,主要的意思就说在Tomcat 8.0版本开始,不需要在设置-PermSize-MaxPermSize这两个参数了。所以在刚刚配置中直接删掉就可以了。 
    OpenJDK 64-Bit Server VM warning: ignoring option PermSize=128M; support was removed in 8.0 
    OpenJDK 64-Bit Server VM warning: ignoring option MaxPermSize=128m; support was removed in 8.0

    配置Tomcat以后台daemon.sh启动配置JVM内存

    综上,已经说明JVM内存的一些注意事情,下面直接描述一下Tomcat通过catalina.sh启动配置JVM内存分配的方法。

    备注:以catalina.sh方式启动Tomcat的方法【点击查看】

    进入%TOMCAT_HOME%/bin目录下,找到daemon.sh脚本。 
    1、测试一下daemon.sh启动服务是否正常。 
    执行下面命令,可以看一下Tomcat一些启动信息。

    备注:从进程信息中我们并没有看到-server -Xms896m -Xmx896m内存分配的信息,也就是说Tomcat的daemon.sh启动脚本并没有继承catalina.sh脚本中的配置信息,所以还需手动为daemon.sh配置JVM内存分配参数。

    [root@iZ28snxdn5mZ bin]# ./daemon.sh start
    [root@iZ28snxdn5mZ bin]# ps -ef | grep tomcat
    root     23891     1  0 20:14 ?        00:00:00 jsvc.exec -java-home /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.161-0.b14.el7_4.x86_64/jre -user www -pidfile /opt/apache/tomcat-8/logs/catalina-daemon.pid -wait 10 -outfile /opt/apache/tomcat-8/logs/catalina-daemon.out -errfile &1 -classpath /opt/apache/tomcat-8/bin/bootstrap.jar:/opt/apache/tomcat-8/bin/commons-daemon.jar:/opt/apache/tomcat-8/bin/tomcat-juli.jar -Djava.util.logging.config.file=/opt/apache/tomcat-8/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Dignore.endorsed.dirs= -Dcatalina.base=/opt/apache/tomcat-8 -Dcatalina.home=/opt/apache/tomcat-8 -Djava.io.tmpdir=/opt/apache/tomcat-8/temp org.apache.catalina.startup.Bootstrap
    www      23892 23891 19 20:14 ?        00:00:01 jsvc.exec -java-home /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.161-0.b14.el7_4.x86_64/jre -user www -pidfile /opt/apache/tomcat-8/logs/catalina-daemon.pid -wait 10 -outfile /opt/apache/tomcat-8/logs/catalina-daemon.out -errfile &1 -classpath /opt/apache/tomcat-8/bin/bootstrap.jar:/opt/apache/tomcat-8/bin/commons-daemon.jar:/opt/apache/tomcat-8/bin/tomcat-juli.jar -Djava.util.logging.config.file=/opt/apache/tomcat-8/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Dignore.endorsed.dirs= -Dcatalina.base=/opt/apache/tomcat-8 -Dcatalina.home=/opt/apache/tomcat-8 -Djava.io.tmpdir=/opt/apache/tomcat-8/temp org.apache.catalina.startup.Bootstrap
    root     23934 23179  0 20:14 pts/0    00:00:00 grep --color=auto tomcat
    [root@iZ28snxdn5mZ bin]# 

    2、使用vim编辑器打开daemon.sh脚本。在该脚本执行语句之前追加下面代码。 
    JAVA_OPTS="-server -Xms896m -Xmx896m"

    [root@iZ28snxdn5mZ bin]# vim daemon.sh
    ...

    在vim下搜索JAVA_OPTS=如下图,在后面配置上JVM内存分配参数. 
    这里写图片描述

    然后保存退出即可。 
    停止服务,重新启动服务。

    [root@iZ28snxdn5mZ bin]# ./daemon.sh stop
    [root@iZ28snxdn5mZ bin]# ./daemon.sh start
    [root@iZ28snxdn5mZ bin]# ps -ef | grep tomcat
    root     23983     1  0 20:22 ?        00:00:00 jsvc.exec -java-home /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.161-0.b14.el7_4.x86_64/jre -user www -pidfile /opt/apache/tomcat-8.5.27/logs/catalina-daemon.pid -wait 10 -outfile /opt/apache/tomcat-8.5.27/logs/catalina-daemon.out -errfile &1 -classpath /opt/apache/tomcat-8.5.27/bin/bootstrap.jar:/opt/apache/tomcat-8.5.27/bin/commons-daemon.jar:/opt/apache/tomcat-8.5.27/bin/tomcat-juli.jar -Djava.util.logging.config.file=/opt/apache/tomcat-8.5.27/conf/logging.properties -server -Xms896m -Xmx896m -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Dignore.endorsed.dirs= -Dcatalina.base=/opt/apache/tomcat-8.5.27 -Dcatalina.home=/opt/apache/tomcat-8.5.27 -Djava.io.tmpdir=/opt/apache/tomcat-8.5.27/temp org.apache.catalina.startup.Bootstrap
    www      23984 23983  7 20:22 ?        00:00:01 jsvc.exec -java-home /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.161-0.b14.el7_4.x86_64/jre -user www -pidfile /opt/apache/tomcat-8.5.27/logs/catalina-daemon.pid -wait 10 -outfile /opt/apache/tomcat-8.5.27/logs/catalina-daemon.out -errfile &1 -classpath /opt/apache/tomcat-8.5.27/bin/bootstrap.jar:/opt/apache/tomcat-8.5.27/bin/commons-daemon.jar:/opt/apache/tomcat-8.5.27/bin/tomcat-juli.jar -Djava.util.logging.config.file=/opt/apache/tomcat-8.5.27/conf/logging.properties -server -Xms896m -Xmx896m -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Dignore.endorsed.dirs= -Dcatalina.base=/opt/apache/tomcat-8.5.27 -Dcatalina.home=/opt/apache/tomcat-8.5.27 -Djava.io.tmpdir=/opt/apache/tomcat-8.5.27/temp org.apache.catalina.startup.Bootstrap
    root     24026 23179  0 20:22 pts/0    00:00:00 grep --color=auto tomcat
    [root@iZ28snxdn5mZ bin]#

     

    展开全文
  • 某硅谷jvm内存分析优化教程,链接失效,请私聊我。某硅谷jvm内存分析优化教程,链接失效,请私聊我。某硅谷jvm内存分析优化教程,链接失效,请私聊我。
  • JVM内存配置优化

    2018-12-04 17:28:54
    jvm优化
  • jvm优化 JVM 内存大小设置

    千次阅读 2018-06-22 17:11:27
    Tomcat的内存溢出本质就是JVM内存溢出,所以在本文开始时,应该先对Java JVM有关内存方面的知识进行详细介绍。一、Java JVM内存介绍JVM管理两种类型的内存,堆和非堆。按照官方的说法:“Java 虚拟机具有一个堆,堆...
  • 数据库简单优化jvm内存数据库简单优化jvm内存数据库简单优化jvm内存数据库简单优化jvm内存
  • JVM内存管理和JVM性能优化

    千次阅读 2015-10-31 17:17:14
     gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存。java语言并不要求jvm有gc,也没有规定gc如何工作。不过常用的jvm都有gc,而且大多数gc都使用类似的算法管理内存和执行收集操作。  在充分理解了...
  • jvm优化(二)JVM 内存大小设置

    万次阅读 2017-12-01 19:58:40
    Tomcat的内存溢出本质就是JVM内存溢出,所以在本文开始时,应该先对Java JVM有关内存方面的知识进行详细介绍。一、Java JVM内存介绍JVM管理两种类型的内存,堆和非堆。按照官方的说法:“Java 虚拟机具有一个堆,堆...
  • JVM 深入学习教程深入分析JVM教程!jvm 内存原型,优化等等
  • 你知道 JVM 进程的内存布局吗?
  • JVM优化系列-JVM内存溢出的原因

    千次阅读 2020-02-23 14:40:42
      内存溢出(OutOfMemory)OOM,通常情况下出现在某一块内存空间快要消耗完的时候。在Java程序中,导致内存溢出的原因有很多,下面就来分享关于内存溢出的一些问题。其中包括堆内存、直接内存溢出、永久区(Java8...
  • Tomcat性能优化JVM内存工作原理,适用于运维人员,开发人员
  • 性能优化JVM内存分配机制
  • JVM内存管理分为两部分: 内存分配 内存回收 ------------------------------------------------------ 内存回收经常也被叫做垃圾回收。(附带资料:JVM面试题超链接、JVM性能调优和 参数说明) *很多人迷惑一...
  • 启动容器,指定jvm 内存参数来降低对服务器内存的消耗 配置前说明环境 笔者的环境:是在pom.xml中,生成的dockerFile ,每次MAVEN install都会生成新的dockerFile,并且会执行docker build (通过docker

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 183,824
精华内容 73,529
关键字:

jvm内存优化