审计Java:检测抛出/捕获异常的系统(aop?)

审计Java:检测抛出/捕获异常的系统(aop?),java,exception,logging,jakarta-ee,aop,Java,Exception,Logging,Jakarta Ee,Aop,由于检查异常,我们可能会在生产中遇到一些问题,因为所有异常都被捕获到正确的位置并正确记录 我想知道是否有一些开源工具来帮助审计这些问题 例如,是否有某种AOP工具可以拦截抛出的所有异常,并查看它们是否被重新抛出、包装或记录?这将有助于识别错误捕获。有一些工具,如FindBugs、PMD和Checkstyle,可以识别一些常见的异常处理问题。如果有人知道我会感兴趣的话,我从未见过专门分析异常处理的工具 如果您决定采用AOP路线,Spring框架提供了一个易于使用的AOP框架。本质上,与Spring

由于检查异常,我们可能会在生产中遇到一些问题,因为所有异常都被捕获到正确的位置并正确记录

我想知道是否有一些开源工具来帮助审计这些问题


例如,是否有某种AOP工具可以拦截抛出的所有异常,并查看它们是否被重新抛出、包装或记录?这将有助于识别错误捕获。

有一些工具,如FindBugs、PMD和Checkstyle,可以识别一些常见的异常处理问题。如果有人知道我会感兴趣的话,我从未见过专门分析异常处理的工具

如果您决定采用AOP路线,Spring框架提供了一个易于使用的AOP框架。本质上,与Spring的大部分功能一样,您将使用xml配置文件和一些java代码的组合来定义您正在寻找的AOP功能

在您的情况下,我相信您会希望定义一个“抛出建议后”,在该建议中,您当然可以访问抛出的异常

Spring文档中的AOP章节是一个很好的文档起点:


哦,我相信所有的Spring项目都是开源的=)

我知道这个问题需要一个开源的解决方案。我不知道有哪一个,但如果有选择的话,它会完全满足你的需求。祝你搜索好运。

我有一个确切的问题,我试图自己写一些东西,由于AOP嵌套代理和缺乏使用指令/编织的能力,我放弃了,只是做了大量的查找和替换


当时我找到的工具之一是BMC软件,但成本高是一个问题

IntelliJ的检查员可以在编写代码时检查代码中的许多问题:

但你的问题听起来更像是教育而不是技术。您需要让您的团队了解适当的异常处理意味着什么,何时应该执行,等等。工具会有所帮助,但最好不要将它们放入代码中

我们在生产系统中使用Spring方面来进行日志记录、跟踪、性能计算等。之前、之后和异常建议都非常有效——它们将代码保存在一个地方,并在应用位置上提供声明性灵活性


只有一个警告:方面不是免费的。它们会增加你应用它们的每一种方法的成本,所以不要把它们堆积起来。所有事情的适度性都是关键。

我还没有想到这一点,但是有一个解决方案,如果您不需要检测在生产环境中引发的异常,那么它就是将一个自定义调试器附加到Java应用程序,每当引发异常时,都可以触发该调试器

这篇法国博客文章讨论了如何做到这一点:

代码如下:

使用调试运行: Xdebug-Xrunjdwp:transport=dt_套接字,地址=8000,服务器=y,挂起=n

连接到JVM:

public static VirtualMachine connect(String port) throws IOException, IllegalConnectorArgumentsException {
        AttachingConnector connector = null;
        VirtualMachineManager vmManager = Bootstrap.virtualMachineManager();
        for (Connector aconnector : vmManager.allConnectors()) {
            if ("com.sun.jdi.SocketAttach".equals(aconnector.name())) {
  connector = (AttachingConnector) aconnector;
  break;
     }
 }
 Map<String, Connector.Argument> args = connector.defaultArguments();
        Connector.Argument pidArgument = args.get("port");
        pidArgument.setValue(port);
        return connector.attach(args);
 }
public static VirtualMachine connect(字符串端口)引发IOException、IllegalConnectorArgumentsException{
AttachingConnector连接器=空;
VirtualMachineManager vmManager=Bootstrap.VirtualMachineManager();
对于(连接器aconconnector:vmManager.allConnectors()){
if(“com.sun.jdi.SocketAttach”.equals(aconconnector.name())){
连接器=(连接连接器)一个连接器;
打破
}
}
Map args=connector.defaultArguments();
Connector.Argument pidArgument=args.get(“端口”);
pidArgument.setValue(端口);
返回连接器。连接(args);
}
创建断点。例如:

public static void createExceptionBreakPoint(VirtualMachine vm) {
        EventRequestManager erm = vm.eventRequestManager();
        List<ReferenceType> referenceTypes = vm.classesByName("java.lang.Throwable");
        for (ReferenceType refType : referenceTypes){
  ExceptionRequest exceptionRequest = erm.createExceptionRequest(refType, true, true);
  exceptionRequest.setEnabled(true);
 }
}
公共静态void createExceptionBreakPoint(VirtualMachine vm){
EventRequestManager erm=vm.EventRequestManager();
List referenceTypes=vm.classesByName(“java.lang.Throwable”);
for(ReferenceType refType:referenceTypes){
ExceptionRequest ExceptionRequest=erm.createExceptionRequest(refType,true,true);
exceptionRequest.setEnabled(true);
}
}
然后处理异常:

public static void handleExceptionEvent(ExceptionEvent exceptionEvent) throws Exception {
        ObjectReference remoteException = exceptionEvent.exception();
        ThreadReference thread = exceptionEvent.thread();
        List<Value> paramList = new ArrayList<Value>(1);
        paramList.add(dumpFileName);
        //crer un printStream dans la JVM cible
        ObjectReference printStreamRef = printStreamClassType.newInstance(thread, printStreamConstructor, paramList,
            ObjectReference.INVOKE_SINGLE_THREADED);
    ReferenceType remoteType = remoteException.referenceType();
    Method printStackTrace = (Method) remoteType.methodsByName("printStackTrace").get(1);
    paramList.clear();
    paramList.add(printStreamRef);
    remoteException.invokeMethod(thread, printStackTrace, paramList, ObjectReference.INVOKE_SINGLE_THREADED);
    Scanner scanner = new Scanner(new File(dumpFileName.value()));
    while (scanner.hasNextLine()){
  System.out.println(scanner.nextLine());
 }
}
public static void handleExceptionEvent(ExceptionEvent ExceptionEvent)引发异常{
ObjectReference remoteException=exceptionEvent.exception();
ThreadReference thread=exceptionEvent.thread();
List paramList=newarraylist(1);
paramList.add(dumpFileName);
//打印流文件的副本
ObjectReference printStreamRef=printStreamClassType.newInstance(线程、printStreamConstructor、paramList、,
ObjectReference.INVOKE_SINGLE_THREADED);
ReferenceType remoteType=remoteException.ReferenceType();
方法printStackTrace=(方法)remoteType.methodsByName(“printStackTrace”).get(1);
paramList.clear();
paramList.add(printStreamRef);
invokeMethod(线程、printStackTrace、paramList、ObjectReference.INVOKE\u单线程);
Scanner Scanner=new Scanner(新文件(dumpFileName.value());
while(scanner.hasNextLine()){
System.out.println(scanner.nextLine());
}
}

有点重,但它可以工作,现在如何捕获记录的异常和其他异常

我确实知道做AOP的工具,也知道如何做,但我想知道是否有人已经做过了!:)我自己当然也使用过Spring AOP,但从来没有按照您的想法使用过。我更多地将其用作开发工具,以删除尚未编码或尚未访问的组件。但最终,我的AOP代码都不会在生产环境中运行。您所说的做的当然更接近于AOP的传统使用方式,但您必须决定是否要在OO应用程序中实现AOP设计元素。OO纯粹主义者可能会不寒而栗,但我会说它确实是一个有用的工具!=)实际上,aop不仅仅是为了开发目的,我想做的完全符合aop