`
supben
  • 浏览: 330186 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JVM异常退出原因追踪

    博客分类:
  • JVM
 
阅读更多
package com.xx;

import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.LockInfo;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MonitorInfo;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.ArrayList;
import java.util.List;

public class Test{
	static {
		/**
		 * 打印JVM退出堆栈信息
		 */
		jvmExitHook();
	}

	public static void jvmExitHook() {
		System.out.println("注册JVM Shutdown钩子方法---------");
		Runtime.getRuntime().addShutdownHook(new Thread() {
			@Override
			public void run() {
				MemoryMXBean memorymbean = ManagementFactory.getMemoryMXBean();
				System.out.println("####################内存信息####################");
				System.out.println("Heap Memory: " + memorymbean.getHeapMemoryUsage());
				System.out.println("Non Heap Memory: " + memorymbean.getNonHeapMemoryUsage());

				List<GarbageCollectorMXBean> list = ManagementFactory.getGarbageCollectorMXBeans();
				if (list != null && list.size() > 0) {
					System.out.println("####################Gc信息####################");
					for (GarbageCollectorMXBean gcBean : list) {
						String s = "gc name=" + gcBean.getName() + ",gc count=" + gcBean.getCollectionCount() + ",gc time=" + gcBean.getCollectionTime();
						System.out.println(s);
					}
				}

				ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
				long[] ids = threadBean.getAllThreadIds();
				System.out.println("####################线程信息####################");
				for (long id : ids) {
					ThreadInfo threadInfo = threadBean.getThreadInfo(id, Integer.MAX_VALUE);
					if (threadInfo != null) {
						String s = "blockcount=" + threadInfo.getBlockedCount() + ",blocktime=" + threadInfo.getBlockedTime();
						s = s + ",waitedcount=" + threadInfo.getWaitedCount() + ",waitedtime=" + threadInfo.getWaitedTime();
						System.out.println(s);
						System.out.println(getThreadInfo(threadInfo));
					}
				}

				long[] deadlock_ids = threadBean.findDeadlockedThreads();
				if (deadlock_ids != null) {
					System.out.println("####################死锁信息####################");
					for (long id : deadlock_ids) {
						System.out.println("死锁的线程号:" + id);
					}
				}
			}

		});
	}

	public static String getThreadInfo(ThreadInfo t) {

		try {
			StringBuilder sb = new StringBuilder("\"" + t.getThreadName() + "\"" + " Id=" + t.getThreadId() + " " + t.getThreadState());
			if (t.getLockName() != null) {
				sb.append(" on " + t.getLockName());
			}
			if (t.getLockOwnerName() != null) {
				sb.append(" owned by \"" + t.getLockOwnerName() + "\" Id=" + t.getLockOwnerId());
			}
			if (t.isSuspended()) {
				sb.append(" (suspended)");
			}
			if (t.isInNative()) {
				sb.append(" (in native)");
			}
			sb.append('\n');
			int i = 0;
			for (StackTraceElement ste : t.getStackTrace()) {
				sb.append("\tat " + ste.toString());
				sb.append('\n');
				if (i == 0 && t.getLockInfo() != null) {
					Thread.State ts = t.getThreadState();
					switch (ts) {
					case BLOCKED:
						sb.append("\t-  blocked on " + t.getLockInfo());
						sb.append('\n');
						break;
					case WAITING:
						sb.append("\t-  waiting on " + t.getLockInfo());
						sb.append('\n');
						break;
					case TIMED_WAITING:
						sb.append("\t-  waiting on " + t.getLockInfo());
						sb.append('\n');
						break;
					default:
					}
				}

				for (MonitorInfo mi : t.getLockedMonitors()) {
					if (mi.getLockedStackDepth() == i) {
						sb.append("\t-  locked " + mi);
						sb.append('\n');
					}
				}
			}
			if (i < t.getStackTrace().length) {
				sb.append("\t...");
				sb.append('\n');
			}

			LockInfo[] locks = t.getLockedSynchronizers();
			if (locks.length > 0) {
				sb.append("\n\tNumber of locked synchronizers = " + locks.length);
				sb.append('\n');
				for (LockInfo li : locks) {
					sb.append("\t- " + li);
					sb.append('\n');
				}
			}
			sb.append('\n');
			return sb.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}
}

 

 找一个类,启动的时候注册进去JVM退出的钩子方法

由于ThreadInfo默认只打出8行堆栈内容,可能会错过我们需要的报错信息。所以改写了toString方法

分享到:
评论

相关推荐

    Java线上故障排查方案(2).pdf

    而业务异常则可能包括服务运行一段时间自动退出、服务间调用时间过长、多线程并发异常、死锁等问题。在进行故障排查时,第一步便是问题的定位,只有找准问题源头,才能制定出合适的解决方案。 在进行问题定位时,...

    JProfiler.11.1.4.rar

    它允许用户查看对象的生命周期,跟踪引用链,并定位导致内存消耗增加的原因。通过这些工具,开发者可以有效地管理和优化应用程序的内存使用。 2. **线程分析**:在JProfiler中,可以实时监控和分析应用程序中的线程...

    Jokenpo:关于著名的石头,剪刀和剪刀游戏的JVM的Kotlin项目

    此外,可能会使用while循环或for循环来重复游戏,直到满足某个结束条件,如达到特定回合数或玩家要求退出。 **4. 异常处理** 虽然在简单的Jokenpo游戏中异常可能较少,但在实际项目中,我们可能需要考虑处理用户...

    彻底找到 Tomcat 启动速度慢的元凶

    然而,即便如此,Tomcat启动依然缓慢,而且在启动过程中,JVM进程已正常启动但并未完成启动过程,排除了JVM异常退出的可能性。随后,进一步排查包括CPU、内存使用率、硬盘空间以及网络I/O等常规检查均未发现问题。 ...

    jvmti_java_jvmti_

    例如,`MethodEnterCallback`和`MethodExitCallback`可以在方法进入和退出时执行自定义代码,用于追踪执行路径或计算性能指标。 3. **数据访问**:JVMTI提供了访问和修改程序状态的能力。这包括读取和修改堆栈帧、...

    Arthas阿尔萨斯使用说明

    1. **类加载问题:** 当遇到类相关的异常时,可以通过Arthas查找出问题类所在的jar包位置及其加载过程中的细节,以便于快速定位问题根源。 2. **代码变更追踪:** 如果遇到修改后的代码未能生效的情况,Arthas能够...

    JAVA常用指令.pdf

    - `logging`:日志记录,用于追踪程序运行情况,便于调试和监控。 以上只是Java编程中的一部分关键概念,实际上Java有着丰富的特性和工具,包括多线程、网络编程、反射、集合框架等,学习和掌握Java需要不断深入...

    Java客户管理系统

    理解JVM(Java虚拟机)的工作原理对于优化系统性能也至关重要。 2. **Java Swing或JavaFX**:这些是用于创建用户界面的库。Java Swing适用于桌面应用程序,提供丰富的组件,如JTable用于显示数据,JOptionPane用于...

    JavaSE笔试问答题.docx

    ErrorCode返回错误是直接返回错误码,异常则会中断当前流程,便于追踪问题。 20. JDK1.7引入了钻石操作符、try-with-resources等,1.8引入了lambda表达式、方法引用来简化代码。 21. 继承是子类继承父类的属性和...

    Java在线问题诊断工具.pdf

    Java在线问题诊断工具是一种用于监控和诊断Java应用程序运行时问题的工具,它可以动态地追踪正在运行的Java程序,而对运行中的代码侵入性小,对性能的影响可以忽略不计。这类工具通常利用Java代码和JavaSE的新特性...

    Arthas - Java 诊断利器.docx

    这个工具的主要目的是帮助开发者在遇到线上问题时能够迅速定位并解决,它提供了丰富的功能,包括动态跟踪代码、实时监控JVM状态以及在线查看和分析Java应用的运行情况。 ### 安装与启动Arthas 安装Arthas非常简单,...

    Java线上故障排查方案.pdf

    2. **业务异常**:如服务运行一段时间后自动退出、服务间调用耗时过长、多线程并发处理时出现问题、线程死锁等。 #### 三、如何定位问题 解决问题的第一步是准确定位问题所在。以下是一些常用的定位手段,可以按照...

    javajava调试java调试java调试java调试

    在Java编程过程中,遇到程序出错或运行异常时,调试是找出问题源头的关键步骤。本文将详细介绍Java调试的一些核心技术和方法。 首先,Java调试的基础是JVM(Java虚拟机)提供的调试接口JDWP(Java Debug Wire ...

    java学习最新英文单词

    - **作用**:便于管理和追踪软件的更新迭代。 ### 7. Author - **定义**:指明代码的作者或贡献者。 - **作用**:对于开源项目来说非常重要,有助于追溯代码的原始来源。 ### 8. Public - **定义**:访问修饰符,...

    MyCleaner:清理一些应用程序的垃圾

    1. **临时文件**:应用程序在运行过程中生成的临时文件,用于存储中间计算结果或配置信息,通常在程序退出后应该被删除,但有时会因为异常退出而遗留下来。 2. **日志文件**:为了追踪程序运行状态和错误,许多应用...

    2019计算机二级测试Java试卷.docx

    **原理**:垃圾回收机制通过追踪对象之间的引用关系来确定哪些对象不再被程序使用,然后释放这些对象所占用的内存空间。常见的算法包括标记-清除算法、复制算法以及分代收集算法等。 25. **构造方法和普通的成员...

    procesoIntercambio

    在Java中,异常处理是通过`try-catch-finally`块来实现的,确保程序在遇到错误时能够优雅地退出,而不是突然崩溃。 6. **数据结构与算法**:"摄食过程"可能需要使用到数据结构(如数组、链表、集合等)来存储和管理...

    java源码调试-JavaOpenResoure:java源码调试项目

    - **单步执行**:Step Into、Step Over和Step Out分别用于进入方法、逐行执行和退出当前方法。 - **查看变量值**:查看局部变量和全局变量的实时值,了解程序运行状态。 - **调用堆栈**:查看调用堆栈可以帮助...

Global site tag (gtag.js) - Google Analytics