zoukankan      html  css  js  c++  java
  • JVM----JVM调优

    工具

      jvisualvm.exe:JDK自带,jdk1.8.0_131in

    方法区内存溢出异常

      jdk1.8和1.7自带的hotspot虚拟机的差异了。从jdk1.8开始,自带的hostspot虚拟机取消了过去的永久区,而新增了metaspace区,从功能上看,metaspace可以认为和永久区类似,其最主要的功用也是存放类元数据,但实际的机制则有较大的不同。首先,metaspace默认的最大值是整个机器的物理内存大小,所以metaspace不断扩张会导致java程序侵占系统可用内存,最终系统没有可用的内存;而永久区则有固定的默认大小,不会扩张到整个机器的可用内存。当分配的内存耗尽时,两者均会触发full gc,但不同的是永久区在full gc时,以堆内存回收时类似的机制去回收永久区中的类元数据(Class对象),只要是根引用无法到达的对象就可以回收掉,而metaspace判断类元数据是否可以回收,是根据加载这些类元数据的Classloader是否可以回收来判断的,只要Classloader不能回收,通过其加载的类元数据就不会被回收。

      方法区溢出也是一种常见的内存溢出异常,一个类如果要被垃圾收集器回收,要达成的条件是比较苛刻的。在经常运行时生成大量动态类的应用场景里,就应该特别关注这些类的回收状况,这类场景除了之前提到的程序使用了CGLib字节码增强和动态语言外,常见的还有:大量JSP或动态产生JSP文件的应用(JSP第一次运行时需要编译为Java类)、基于OSGI的应用(即使是同一个类文件,被不同的加载器加载也会被视为不同的类)。

      使用jdk的动态代理不会造成方法区内存溢出,使用cglib动态代理,如果设置了enhancer.setUseCache(false)【默认是true】,就有可能造成方法区溢出,原因是不使用缓存,无限创建动态代理,生成class对象。

    内存溢出解决情况

      可以加参数,如果发送内存溢出自动生成dump文件,然后用jvisualvm.exe,查看dump文件,检查那个对象占用的内存最多,通过业务代码分析原因

    -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:srvdump
    

      

    设置GC日志

    参考:https://blog.csdn.net/goldenfish1919/article/details/93997132

    -XX:+PrintGCDetails 
    -XX:+PrintGCDateStamps
    #%t会给文件名添加时间戳后缀,格式是YYYY-MM-DD_HH-MM-SS
    -Xloggc:/home/GCEASY/gc-%t.log
    -XX:+UseGCLogFileRotation
    #最多是5个日志文件
    -XX:NumberOfGCLogFiles=5
    #每个日志文件大小是20M
    -XX:GCLogFileSize=20M

    PS-PO垃圾收集器的日志分析

    2021-01-10T21:52:59.360+0800: 1.366: [Full GC (Ergonomics) [PSYoungGen: 15872K(年轻代回收前)->13154K(年轻代回收后)(17920K)(总大小)] [ParOldGen: 511K->511K(512K)] (如果没有就是没有回收老年代)16383K(整个堆回收前)->13665K(整个堆回收后)(18432K)(总大小), [Metaspace: 3590K->3590K(1056768K)], 0.1673693 secs] [Times: user=0.30 sys=0.00, real=0.17 secs]

    GC垃圾收集器

    https://blog.csdn.net/varyall/article/details/81634272?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control

    GC优化归纳了两个目的:

    • 一个是将转移到老年代的对象数量降到最少
    • 另一个是减少Full GC的执行时间

    频繁GC的检查方法

    1、硬件本身设置的内存少,内存不够

    2、扩展内存后,频繁GC,并且内存空间不释放(对象无法回收)

    排查(简单):

    1、jps 或者ps -ef|grep java 或者top :查看正在运行的程序,top可以查看进程占用cpu和内存,可以top监听一下程序,如果一个程序内存一直在上升,不释放,那可能就有问题了

    2、jmap -histo [PID] head -20:查看比较占内存的对象以及数量以及占用空间大小,可以多执行几次

      实际当中用不了,如果实际当中生产服务器内存10g,一个jmap命令,可能服务就要停好几个小时。

      一般使用JVM加参数,-XX:+HeapDumpOnOutOfMemoryError,参数表示当JVM发生OOM时,自动生成DUMP文件。-XX:HeapDumpPath=${目录}参数表示生成DUMP文件的路径,也可以指定文件名称,例如:-XX:HeapDumpPath=${目录}/java_heapdump.hprof。如果不指定文件名,默认为:java_<pid>_<date>_<time>_heapDump.hprof。

    3、查看业务逻辑,为啥这个对象一直生成,并且无法回收

    附加

    查看线程情况

      top -Hp pid:查看进程中不同的线程占用内存空间(-H 显示线程信息,-p指定pid)

      jstack pid :该进程所有的线程列举出来,通过线程调用栈排查问题。

      https://www.cnblogs.com/shengulong/p/8513652.html

    tomcat出现

    Unloading class sun.reflect.GeneratedMethodAccessor的原因

      这表示方法区已经满了,现在在这卸载方法区里面的类,这是正常的现象,说明大量使用反射生成的class被jvm正确回收了。 

      在大量使用发射、动态代理、cglib等框架比如Spring、hibernate等,都需要虚拟机具备类卸载的功能,以保证方法区不会溢出。如果限制类卸载功能及限制 PermSize大小,相信方法区很快就会溢出。所以那些“奇怪信息”也属于正常的输出。另外也可以通过调大 PermSize的值已保证有足够的空间来装载这些类信息,这样,“这些信息”就可能不会输出了。

  • 相关阅读:
    JAVA的泛型与反射的联合应用
    jsp文件过大,is exceeding 65535 bytes limit
    Eclipse闪退解决方案
    EL中定义函数
    JAVA开发工作流程
    理解HTTP协议
    umask函数
    utime修改文件的存取,修改时间
    Linux C ftruncate 函数清空文件注意事项(要使用 lseek 重置偏移量)
    如何实现多进程写一个文件
  • 原文地址:https://www.cnblogs.com/yanxiaoge/p/14254831.html
Copyright © 2011-2022 走看看