使用Instrumentation记录未处理的异常 [英] Using Instrumentation to record unhandled exception

查看:246
本文介绍了使用Instrumentation记录未处理的异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用检测来调试java应用程序。当前系统的问题是

I was trying to debug java application using instrumentation. The problem with current system are


  • 几乎没有写任何日志语句

  • 异常处理不当

这很难追查功能损坏的根本原因。

This made very difficult to trace root cause of broken functionality.

要处理情况我已经使用 Instrumentation API开发了工具,java代理,我能够注入日志语句并解决了一半的问题。

To handle the situation I have developed tool,java agent using Instrumentation API , and I was able to inject log statements and half of the problem solved.

但下一个问题是记录异常。我想在应用程序执行期间抛出的每个异常都扩展我的工具记录。我尝试使用 javaassist API为方法注入try-catch块(使用 addCatch insertBefore insertAfter ),并且在某种程度上有效。

But the next problem is to recording the Exception. I want to extend my tool record every exception thrown during the execution of the application. I tried injecting 'try-catch' block using javaassist API for methods (using addCatch, insertBefore and insertAfter), and it is effective certain extent.

public byte[] transform(ClassLoader    loader,
        String              className,
        Class<?>            classBeingRedefined,
        ProtectionDomain    protectionDomain,
        byte[]              classfileBuffer)
        throws IllegalClassFormatException {
     if (className.startsWith("com/alu/")) {
          return insertLog(className, classBeingRedefined, classfileBuffer);
     }

     if(className.endsWith("Exception")){
         System.out.println("============= exception occured "+className);
     }

这里 inserLog(..)方法将注入必要的日志语句并且工作正常,但是当有任何异常时它不会变成变换器。

Here inserLog(..) method will inject necessary log statement and works fine,but when there is any Exception it doesn't come to transformer.

但问题是一些方法处理内部异常(即使没有log / sysout)。

But the problem is some of the method handles exception inside ( even with out log/sysout).

例如:

try {
            if(search.equals("Category")){
                //do operation
            }
        } catch (Exception e) {
        }

的值 NullPointerException >是null,我从来不知道这个异常,应用程序失败了。

This code eats NullPointerException when value of search is null, I never know this exception and application fail for some thing else.

最终我想要的是一种机制来记录应用程序抛出的任何异常。以下详细信息将被捕获

Ultimately what I want is a mechanism to record any exception thrown by application. following details are to be captured


  • 异常类型

  • Excpetion Stacktrace

  • 方法和类名

我知道有API Thread.setDefaultUncaughtExceptionHandler ,但不确定它如何与java检测一起使用。我没有任何来源访问该应用程序。

I know there is API Thread.setDefaultUncaughtExceptionHandler, but not sure how it use with java instrumentation. I don't have any source access the application.

[更新1]

我发现下面的链接告诉使用重新转换,我会试一试并更新

I found below link tells to use retransformation , I will give a try and update

如何监控java系统类?

任何指导都会有很大帮助。

Any guidance would be greatly helpful.

推荐答案

我认为你应该使用ASM直接操作字节码。这是algoritms:

I think you should use ASM to manipulate bytecode directly. Here is algoritms:


  1. 访问所有try / catch块(参见 visitTryCatchBlock )并保存所有处理程序标签

  2. 访问指令,直到其中一个处理程序符合标签。

  3. 处理程序标签后插入日志代码

  1. Visit all try/catch blocks (see visitTryCatchBlock) and save all handler labels
  2. Visit instructions until one of the handler labels met.
  3. After handler label insert logging code

GETSTATIC java/lang/System out
LDC "exception X occured"
INVOKEVIRTUAL java/io/PrintStream println (java/lang/String)V


并确保您的javaagent正常工作。检查您的MANIFEST.MF文件是否包含正确的 premain 声明并启用类转换。

And ensure that your javaagent works fine. Checkt that your MANIFEST.MF file contains proper premain declaration and enables class transformation.

关于您当前的代码。这里

About your current code. Here

 if (className.startsWith("com/alu/")) {
      return insertLog(className, classBeingRedefined, classfileBuffer);
 }

您转换特定包中的类。这些类包含的代码特别是抛出异常。

you transforming classes inside particular package. That classes contain code that, in particular, throw exceptions.

这里

 if(className.endsWith("Exception")){
     System.out.println("============= exception occured "+className);
 }

您在JVM首次加载时重新编译的类的日志,当它的时候名称以例外结尾。不是在发生异常时。但转换异常本身是没用的。所以我想你应该这样做:

you log of class being retransfomed when it is first loaded by JVM, when its name ends with "Exception". Not when exception occured. But transforming exception is useless itself. So I guess you should proceed like this:

if (className.startsWith("com/alu/")) {
    System.out.println("============= class transformed "+ className);
    return insertLog(className, classBeingRedefined, classfileBuffer);
} 

所以你可以知道你的代理人至少有效。

So you could know that your agent at least works.

你必须处理这样的代码

    try {
        if(search.equals("Category")){
            //do operation
        }
    } catch (Exception e) {
    }

吞下异常。你转换它们将是这样的方法:

where exceptions are swallowed. You transform methods that they will be like this:

try {
    try {
        if(search.equals("Category")){
            //do operation
        }
    } catch (Exception e) {
    }
} catch (Exception e) {
    e.printStackTrace();
}

当然,当第一个吞下异常时赶上,第二个永远不会碰到它。相反,您应该转换现有的 catch 阻止自己,以获取以下代码:

Of course, when exception was swallowed by the first catch, the second one never cathes it. Instead, you should transform existing catch blocks themself, to get the following code:

try {
    if(search.equals("Category")){
        //do operation
    }
} catch (Exception e) {
    e.printStackTrace();
}

上面我向您展示了如何使用ASM实现这一目标。

Above I shown you how to achieve this with ASM.

这篇关于使用Instrumentation记录未处理的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆