ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java项目运维总结记录

2021-07-18 13:02:31  阅读:143  来源: 互联网

标签:总结 java 运维 报错 线程 Java net rmi 异常


一、常见故障

1.1、Java项目CPU耗用突增100%分析定位

1)执行top命令确认当前占用cpu的的java进程;以下是一些快捷键:

?:显示在top当中可以输入的命令 P:以CPU的使用资源排序显示 M:以内存的使用资源排序显示 N:以pid排序显示 T:由进程使用的时间累计排序显示 k:给某一个pid一个信号。可以用来杀死进程 r:给某个pid重新定制一个nice值(即优先级) q:退出top(用ctrl+c也可以退出top)。

2)确认异常进程的具体线程:上述界面按H键或执行top -Hp java_Pid,然后记录异常线程的pid;

另外:ps -eLf | grep java也可查看 //e是显示全部进程,L是显示线程,f全格式输出;其中LWP( (light weight process, 轻量级进程,即线程标识符,NLWP为线程数量)列即线程的pid;

或ps -mp pid号 -o THREAD,tid,lwp,nlwp,time,rss,size,%mem //查看LWP

或htop命令,按t(显示进程线程嵌套关系)和H(显示线程) ,然后F4过滤进程名;

jstack命令生成的thread dump信息包含了JVM中所有存活的线程,为了后续追踪查看该线程的堆栈情况,分析指定线程,必须找出对应线程的调用栈,在thread dump中每个线程都有一个nid(native thread id,每一个都对应线程的tid(即top里看到的线程pid,又称java线程的内存地址),可在/proc/pid/task/下查看对应文件,但这里显示的10进制的,而nid显示为16进制的,需转换以下来对应起来),找到对应的nid即可,另在dump信息中,线程主要呈现这3种状态:RUNNABLE,线程处于执行中;BLOCKED,线程被阻塞;WAITING,线程正在等待

3)查看线程的内存:printf ‘%x’ 线程_pid,可得到线程的内存指针或地址,记录该16进制值a;

4)跟踪异常进程:jstack java_Pid > my.log //查看该线程当前的堆栈状态

5)查看上述输出日志:less my.log|grep a //通过上述的线程内存地址确认线程相关的堆栈调用情况,比如下图:
在这里插入图片描述
通过nid16进制246定位到该位置,然后再com部分可看到对应的业务堆栈调用,该线程一直在执行JstackCase类第33行的calculate方法,得到这个信息,就可以检查对应的代码是否有问题。

堆栈,消息模式为FILO(先进后出),某线程堆栈调用(实际就是相关函数调用的时候参数和局部变量的入栈和出栈等),我们知道异常堆栈的顺序应该是从下往上看,异常是一层一层地往外抛出,直至抛出到最外层(即没有catch为止)。最上面的堆栈异常只是真正异常的一个外层表现而已,异常的根源还是要看堆栈最底部的信息。

通过堆栈异常信息中的at字段可看到直接导致发生异常的包名-类名-方法名-代码行数

6)异常堆栈产生的流程:

示例:

package com.bsx.test;

public class TestException {
    public static void main(String[] args) {
        TestException exception = new TestException();
        exception.m1();
    }

    public void m1() {
        m2();
    }

    public void m2() {
        m3();
    }

    public void m3() {
        String name = null;
        System.out.println(name.length());
    }

}

执行后,异常输出如下:

Exception in thread "main" java.lang.NullPointerException
	at com.bsx.test.TestException.m3(TestException.java:22)
	at com.bsx.test.TestException.m2(TestException.java:17)
	at com.bsx.test.TestException.m1(TestException.java:13)
	at com.bsx.test.TestException.main(TestException.java:9)

Java语言的异常类Exception包含着异常的全部信息。从代码及异常输出我们可以知道,这个错误日志输出的顺序跟调用顺序是相反的,我们知道java的方法在执行的时候是在虚拟机栈中执行的,每执行一个方法就会新建一个栈帧然后压入到虚拟机栈中。这是一个后进先出的结构,所以报错的时候也是从被调用者最开始报错,即M3函数先报错,但是是先执行的main函数,然后调用者依次报错,所以打印错误时的顺序也是最从调用报错的位置在最上面,调用者依次向后排。由此我们可以得出堆栈异常信息输出结论:上面报错,下面(调用)跟随。

因此,我们可认为最根本的报错位置在最上面。大部分情况下,最上方的报错信息就是我们代码出错的位置。但是有时最上方的日志不一定是我们自己的代码,比如当你的代码调用了一些三方jar包的代码。但是这并不影响我们去定位问题,我们还是根据最上面报错,来逐步定位问题,因真正报错的位置还是在上面,它就是异常抛出的点。那么我们只需要从上往下依次找我们自己的代码即可。第一个找到的我们的代码位置就是我们代码中引发报错的位置。有时候有些报错信息很明显,我们可以根据报错信息来直接定位到问题症结。有时候报错信息并不能很明确的指明报错原因,这时候,我们就可以在这个精确的位置打上断点来调试一下。

示例2:

javax.naming.ServiceUnavailableException [Root exception is java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is:   //该异常在javax.naming包里面,异常的继承结为:java.lang.Exception---->javax.naming.NamingException--->javax.naming.ServiceUnavailableException
其中,javax.naming.NamingException:此异常是 Context 和 DirContext 接口中的操作抛出的所有异常的超类。失败的特性由子类的名称描述。此异常捕获指出操作失败处的信息,比如解析最后进行到的位置。javax.naming.ServiceUnavailableException:当试图与目录或命名服务通信,而该服务不可用时,抛出此异常。该服务可能因为各种原因而不可用。例如,服务器可能太忙而无法为请求提供服务,或者服务器可能没有为向某些请求提供服务而注册等等。最原始的异常是java.rmi.ConnectException.相关的描述是连接被拒绝。而这个异常中嵌套的异常是java.net.ConnectException 连接被拒绝。java.rmi.ConnectException的父类为java.rmi.RemoteException;RemoteException 是许多与通信相关的异常的通用超类,这些异常可能会在执行远程方法调用期间发生。

远程接口(扩展 java.rmi.Remote 的接口)的每个方法必须在其 throws 子句中列出 RemoteException。java.rmi.Connection:如果拒绝远程主机对连接的远程方法调用,则抛出 ConnectException。

######
java.net.ConnectException: Connection refused: connect]

at com.sun.jndi.rmi.registry.RegistryContext.rebind(RegistryContext.java:142)

at com.sun.jndi.toolkit.url.GenericURLContext.rebind(GenericURLContext.java:231)

at javax.naming.InitialContext.rebind(InitialContext.java:408)

at com.net.rmi.hello.SimpleServer.main(SimpleServer.java:13)

Caused by: java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is:

java.net.ConnectException: Connection refused: connect

at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:601)

at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:198)

at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:184)

at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:322)

at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)

at com.sun.jndi.rmi.registry.RegistryContext.rebind(RegistryContext.java:140)

... 3 more

Caused by: java.net.ConnectException: Connection refused: connect

at java.net.PlainSocketImpl.socketConnect(Native Method)

at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)

at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)

at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)

at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)

at java.net.Socket.connect(Socket.java:519)

at java.net.Socket.connect(Socket.java:469)

at java.net.Socket.(Socket.java:366)

at java.net.Socket.(Socket.java:180)

at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:22)

at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:128)

at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:595)

1.2、堆栈异常

eg1:多线程竞争synchronized锁
在这里插入图片描述
如上图所示,线程1获取到锁,处于RUNNABLE状态,线程2处于BLOCK状态

1、locked <0x000000076bf62208>说明线程1对地址为0x000000076bf62208对象进行了加锁;

2、waiting to lock <0x000000076bf62208> 说明线程2在等待地址为0x000000076bf62208对象上的锁;

3、waiting for monitor entry [0x000000001e21f000]说明线程1是通过synchronized关键字进入了监视器的临界区,并处于"Entry Set"队列,等待monitor

eg2:
在这里插入图片描述
上图中,线程1和2都处于WAITING状态

1、线程1和2都是先locked <0x000000076bf62500>,再waiting on <0x000000076bf62500>,之所以先锁再等同一个对象,是因为wait方法需要先通过synchronized获得该地址对象的monitor;

2、waiting on <0x000000076bf62500>说明线程执行了wait方法之后,释放了monitor,进入到"Wait Set"队列,等待其它线程执行地址为0x000000076bf62500对象的notify方法,并唤醒自己。

1.3、

标签:总结,java,运维,报错,线程,Java,net,rmi,异常
来源: https://blog.csdn.net/ximenjianxue/article/details/118873213

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有