您好,欢迎访问三七文档
当前位置:首页 > 办公文档 > 其它办公文档 > WEBLOGIC企业级运维实战-笔记
常见问题的解决一,内存溢出1,定位是永久区溢出OutOfMemoryError:JavaPermanentSpace还是堆区溢出OutOfMemoryError:Javaheapspace2,原因堆内存溢出:(1)没有分配足够的堆内存(2)内存泄漏(3)内存碎片,则让jvm收集碎片非堆内存溢出:(1)用了JNI本地代码(2)非堆内存少(3)RAM不足二,内存泄漏1,定位Step1系统响应慢,内存占用高,但是访问量不大;Step2控制台强制垃圾回收,内存还是不小;Step3通过分析GC日志,发现fullGC都在回收年青区的对象。同时观测发现,fullgc时cpu高,不fullgc时cpu正常。且从每次GC前后内存比较,内存在累积增加。Step4如果有heapdump分析工具,可以看见内存累积增加,且能定位到哪个对象个数占用内存在多次GC后仍增加。如果没有内存分析工具,看日志,看内存增大前,做了哪些操作,大体能定位到问题的模块。2,原因(1)代码用了Collection,但是没有v[--size]=null(2)对象活动时间太长比如http会话(3)缓存了太多对象,则用软连接(4)大循环(比如死循环)重复产生大量新对象三,连接泄漏1,现象(1)Connection连接池沾满了,但是WLsocket线程很少。可能有ResourceException异常可能是连接泄漏2,方案EnableConnectionLeakProfiling开启连接池泄漏的监控,但是耗资源四,线程死锁1,现象找到stuck线程,如果waitingformonitorentry,如果大量线程都在等给同一地址上锁,五,查找耗用CPU高的线程1、topas查看占用cpu占用最高的进程的PID2、执行:ps-mpPID-oTHREAD以查找相应进程下所有正在占用CPU的线程的TID3、将步骤2中找到的占用CPU高的线程TID转换成16进制,用对应的16进制数值在3步骤中生成的javacore文件中查找对应的线程堆栈(nativeID为该16进制值)六,服务器挂起1,现象WL不响应用户请求,但是也没有明显错误。也就是反应慢2,原因(1)配置的线程数不足增加总体线程数特别socketReader的线程数(2)垃圾回收花费时间增加堆内存,增加年轻代内存,采用不同的垃圾收集器。(3)线程死锁(4)Jdbc死锁(5)等待远程调用(6)JSP正在编译参《分布式JAVA应用基础与实践P63》内存区分为方法区、堆、本地方法栈、PC寄存器、JVM方法栈。其中方法区在堆区里,方法区和堆区是线程共享,其余的是每个线程一份。方法区位于permanentGeneration持久代,通过-xx:permSize和—XXMaxpermSize设置最大和最小值堆区所有new的对象都在这里,通过-xms,-xmx定最大和最小值。当空余堆内存小于40%,会增加heap到-xmx的大小,为了避免运行时频繁调整heap大小,将-xms,-xmx设置成一样。新生代用-xmn设置其大小旧生代:多次回收垃圾任然存活的对象,如缓存对象。也可以是大对象,可以通过-xx:pretenureSizeThreshold来设置对象过大于这个值就放旧生代;还可以是大数组放旧生代。本地方法栈:就是存储了每个native方法调用的状态。PC寄存器占用的是CUP寄存器。JVM方法栈空间不足时会有stackoverflowError错误,可用-Xss来指定大小。新生代用Copying算法.并行收集器用标记-整理来回收年老代,并发收集器用标记-清除来回收年老代JVM相关概念Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人想出来。1,内存区域牛:虚拟机栈:是线程独有的,每次启动一个线程,就创建一个jvm虚拟机栈,线程退出的时候就销毁。这里面主要保存线程参数变量和局部变量值。堆:主要保存创建的Class类的对象,这个Class类的对象link到方法区的数据结构,特别的实例变量在本区。方法区:方法的字节码、静态成员变量、类的数据结构。常量池:方法区的一部分,主要保存class内存结构中常量值例如String值,publicstaticfinal类型的值堆区细分:P60Jvm的heap区包括Yong(年轻代)和Tenured(年老代)区,yong区又分eden,survivor区Tenured区里的对象生命周期长。还有Perm(持久代)区;运行数据区包括栈内存stack,是在线程创建的时候创建的,它的生命周期随线程的生命周期,线程结束内存也释放,所以对于栈来说不存在垃圾回收问题。栈中的数据都是以栈帧(stackframe)的格式存在,当A方法被调用时就产生了一个帧栈F1,被压入栈中,A方法又调用的B方法,于是B产生的帧栈F2也被压入栈,执行完毕后,先弹出F2帧栈,在弹出F1帧栈,遵循“先进后出”原则。帧中存放的数据有三类:堆内存Heap2,标记算法就是决定哪些对象需要回收(1)引用计数法每个对象上都有一个引用计数,对象每被引用一次,引用计数器就+1,对象引用被释放,引用计数器-1,直到对象的引用计数为0,对象就标识可以回收。缺点是A引用用B,B引用A,这两个都不会被回收(2)root搜索法这种算法目前定义了几个root,也就是这几个对象是jvm虚拟机不会被回收的对象,所以这些对象引用的对象都是在使用中的对象,这些对象未使用的对象就是即将要被回收的对象。简单就是说:如果对象能够达到root,就不会被回收,如果对象不能够达到root,就会被回收。A引用用B,B引用A,但是两个都没有被root应用,可以被回收。jvm在确定是否回收的对象的时候采用的是root搜索算法来实现。在root搜索算法的里面,我们说的引用这里都指定的是强引用关系。所谓强引用关系,就是通过用new方式创建的对象,并且显示关联的对象Objectobj=newObject();以上就是代表的是强引用关系,变量obj强引用了Object的一个对象。java里面有四种应用关系,从强到弱分别为:StrongReference(强引用)–WeakReference(弱引用)-SoftReference(软引用)–PhantomReference(虚引用)StrongReference:只有在引用对象root不可达的情况下才会标识为可回收,即使JVM堆内存不够WeakReference:即使在root算法中其引用的对象root可达到,但是如果jvm堆内存不够的时候,还是会被回收。SoftReference:无论其引用的对象是否root可达,在响应内存需要时,由垃圾回收判断是否需要回收。PhantomReference:在回收器确定其指示对象可另外回收之后,被加入垃圾回收队列.2,垃圾收集算法(1)标记-清除(Mark-sweep):首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象(如果对象在进行根搜索后发现没有与GCRoots相连接的引用链,对象将会被标记)。也就是空间A上直接把对象的空间给清除了,缺点是会有碎片,效率也不高(2)复制算法(Copying),它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。缺点是会浪费一半空间(3)标记-整理(Mark-Compact)标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动(区别于copy,是移动哦),然后直接清理掉端边界以外的内存。(4)分代收集(GenerationalCollection)当前商业虚拟机的垃圾收集都采用这种算法,它并没有什么新的思想,只是根据对象的存活周期的不同将内存划分为几块。一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,因为copying算法最快,就是发现eden空间不够了,就拷贝到survivor1区,再拷贝到survivor2区,再拷贝到老年区。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或“标记-整理”算法来进行回收。并行收集器用标记-整理来回收年老代,并发收集器用标记-清除来回收年老代4,回收器选择JVM给了三种选择:串行收集器(Serial)、并行收集器(Parallel)、并发收集器(Concurrent),但是串行收集器只适用于小数据量的情况,JDK5.0以前都是使用串行收集器,JDK5.0以后,JVM会根据当前系统配置进行判断。吞吐量优先的并行收集器,适用于科学技术和后台处理等。响应时间优先的并发收集器,适用于应用服务器、电信领域等。://blog.csdn.net/java2000_wl/article/details/8030172串行收集器:用单线程处理所有垃圾回收工作,适合单处理器机器。并行收集器:用多线程处理所有垃圾回收工作。多CUP,要求高吞吐量,对响应时间无要求的项目,适用于科学技术和后台处理。并发收集器:只是并发收集保留了应用的线程在执行,就是应用程序不需要暂停可以和垃圾回收线程并发工作,由于在应用运行的同时进行垃圾回收,所以有些垃圾可能在垃圾回收进行完成时产生,这样就造成了“FloatingGarbage”,这些垃圾需要在下次垃圾回收周期时才能回收掉。所以,并发收集器一般需要20%的预留空间用于这些浮动垃圾,需要预留足够的内存空间给用户线程使用。适用于对响应时间要求高的,多CPU,大型应用,比如页面请求/web服务器。前端业务系统用的比较多。缺点:在并发阶段,虽然不会导致用户线程停顿,但是会占用CPU资源而导致引用程序变慢,总吞吐量下降。5,内存泄漏的典型代码://tomyz0223.iteye.com/blog/639623publicclassTest{privatestaticVectorv=newVector(10);publicvoidadd(){for(inti=1;i100;i++){Objecto=newObject();v.add(o);o=null;}}publicObjectpop(){returnv[--size];}}集合类,集合类仅仅有添加元素的方法,而没有相应的删除机制,导致内存被占用。这一点其实也不明确,这个集合类如果仅仅是局部变量,根本不会造成内存泄露,在方法栈退出后就没有引用了会被jvm正常回收。而如果这个集合类是全局性的变量(比如类中的静态属性),那么没有相应的删除机制,很可能导致集合所占用的内存只增不减,因此提供这样的删除机制或者定期清除策略非常必要。这里(1)v变量是static(2)虽然o=null;通过v还能访问到o,所以虽然o=null,但o指向的那个对象仍然能通过v访问到,所以GC不会回收的。(3)可以通过v[--size]=null;来释放Vector对对象的引用;或者V=null也可以6,典型线程死锁的代码对象a使用独立线程
本文标题:WEBLOGIC企业级运维实战-笔记
链接地址:https://www.777doc.com/doc-5455122 .html