SetUncaughtExceptionHandler does not work in Maven project

I'm trying to handle excluded exceptions from the main thread in my application, so I can write them to a file (my application is a command line application that works on a night task, so if something goes wrong, I want administrators to be able to easily see exceptions). I shortened this to a simple test case as far as I can.

Maven application generated by ( getting started ):

   mvn -B archetype:generate \
      -DarchetypeGroupId=org.apache.maven.archetypes \
      -DgroupId=com.mycompany.app \
      -DartifactId=my-app

App.java:

package com.mycompany.app;

public class App {

    public static void main(String[] args) throws Exception {
        Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println("Handled exception - let log it!");
                // Logging code here
            }
        });

        System.out.println("Exception testing");
        throw new Exception("Catch and log me!");
    }

}

Starting with mvn exec:javacalls:

[INFO] Error stacktraces are turned on.
[INFO] Scanning for projects...
[WARNING] 
[WARNING] Some problems were encountered while building the effective model for com.mycompany.app:my-app:jar:1.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.version' for org.codehaus.mojo:exec-maven-plugin is missing. @ line 20, column 15
[WARNING] 
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING] 
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING] 
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- exec-maven-plugin:1.4.0:java (default-cli) @ my-app ---
Exception testing
[WARNING] 
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:293)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.Exception: Catch and log me!
    at com.mycompany.app.App.main(App.java:14)
    ... 6 more
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.493 s
[INFO] Finished at: 2015-10-26T10:57:00+00:00
[INFO] Final Memory: 8M/240M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.4.0:java (default-cli) on project my-app: An exception occured while executing the Java class. null: InvocationTargetException: Catch and log me! -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.4.0:java (default-cli) on project my-app: An exception occured while executing the Java class. null
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:216)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:307)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106)
    at org.apache.maven.cli.MavenCli.execute(MavenCli.java:862)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:286)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:197)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
Caused by: org.apache.maven.plugin.MojoExecutionException: An exception occured while executing the Java class. null
    at org.codehaus.mojo.exec.ExecJavaMojo.execute(ExecJavaMojo.java:345)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
    ... 20 more
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:293)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.Exception: Catch and log me!
    at com.mycompany.app.App.main(App.java:14)
    ... 6 more

The same code as a simple Java application works fine. App.java:

public class App {

    public static void main(String[] args) throws Exception {
        Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println("Handled exception - let log it!");
                // Logging code here
            }
        });

        System.out.println("Exception testing");
        throw new Exception("Catch and log me!");
    }

}

The launch javac App.java && java Appcauses:

Exception testing
Handled exception - let log it!

, , , " - ", , , Maven non-Maven.

+4
1

JavaExecMojo . main , mojo. , , jvm.

, maven exec. ExecJavaMojo.

JavaExecMojo

Thread.currentThread().getThreadGroup().uncaughtException( Thread.currentThread(), e );

. , uncaughtException ThreadGroup JVM , . . Javadoc ThreadGroup.uncaughtException( t, Throwable e).

Java, - , Thread.UncaughtExceptionHandler, .

,

try {
   .... 
   // invoke main method
} catch (Exception e) {
  Thread currentThread = Thread.currentThread();
  Thread.UncaughtExceptionHandler ueh = currentThread.getUncaughtExceptionHandler();
  if (ueh == null) {
    currentThread.getThreadGroup().uncaughtException(currentThread, e);
  } else {
    ueh.uncaughtException(currentThread, e);
  }
}

JVM.

defaultUncaughtExceptionHandler .

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
  public void uncaughtException(Thread t, Throwable e) {
    System.out.println("Handled exception - let log it!");
    // Logging code here
  }
});

defaultUncaughtExceptionHandler java.lang.reflect.InvocationTargetException.

. . ThreadGroup. . IsolatedThreadGroup

class IsolatedThreadGroup extends ThreadGroup {
     private Throwable uncaughtException; // synchronize access to this

     public IsolatedThreadGroup( String name ){
        super( name );
     }

    public void uncaughtException( Thread thread, Throwable throwable ) {
        if ( throwable instanceof ThreadDeath ) {
           return; // harmless
        }
        synchronized ( this ) {
            if ( uncaughtException == null ) {
                uncaughtException = throwable; // will be reported eventually
           }
        }
        getLog().warn( throwable );
    }
 }

javadoc uncaughtException ,

uncaughtException ThreadGroup :

  • , uncaughtException .
  • , , , uncaughtException .
  • , Throwable ThreadDeath. , . , , getName , , Throwable printStackTrace, .

, api. defaultUncaughtExceptionHandler .

JavaExecMojo. ExecMojo. .

 mvn exec:exec -Dexec.executable="java" -Dexec.workingdir="someDir" -Dexec.args="-cp target/classes"

pom, . .

<workingdir>${basedir}</workingdir>
<args>-cp ${project.build.outputDirectory}</args>
+2

Source: https://habr.com/ru/post/1613182/


All Articles