Attach jdb on uncaught exception

末鹿安然 提交于 2019-11-29 15:37:31

问题


So, I am starting a Java program as below

java -agentlib:jdwp=transport=dt_socket,address=8000, server=y,suspend=n  MyClass

I then manually attach a debugger as below

jdb -attach 8000

I would like to know if there is anyway for me to set up jdb so that it automatically attaches to the running process (only) in the case of an uncaught exception?

The reason being that I would like to avoid the overhead of the debugger until an uncaught exception arises. But the problem I face now is that if the debugger is not attached, then the JVM aborts once an uncaught exception arises.

EDIT:

From the Oracle docs, it seems the below command does what I need, but for windows machines.

java -agentlib:jdwp=transport=dt_shmem,server=y,onuncaught=y,launch=d:\bin\debugstub.exe MyClass

Anyone knows the linux equivalent? I have tried the below command.

java -agentlib:jdwp=transport=dt_socket,address=8000,server=y,onuncaught=y,suspend=n,launch=jdb MyClass

The debugger seems like it connects but it immediately throws an IOError.

Initializing jdb ...

java.io.IOException: Input/output error
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:272)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:273)
at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:154)
at java.io.BufferedReader.readLine(BufferedReader.java:317)
at java.io.BufferedReader.readLine(BufferedReader.java:382)
at com.sun.tools.example.debug.tty.TTY.<init>(TTY.java:751)
at com.sun.tools.example.debug.tty.TTY.main(TTY.java:1067)

回答1:


To attach a debugger just in time does indeed use the options you suggest (launch and onuncaught). But the launch option needs more on linux:

Note that the launched process is not started in its own window. In most cases the launched process should be a small application which in turns launches the debugger application in its own window.

In your case, jdb is failing to open the terminal TTY it needs because of the context it is being started in. Depending on the environment where this is running, you will need to construct a script that launches jdb in a new window or attaches it to a pseduo-tty so that it can run properly.

I tested this by creating a script that uses screen to start the terminal

#!/bin/bash
# according to launch option doc, the first argument is the transport and
# the second argument will be the address
#
screen -dm -L -S autojdb jdb -attach $2

This script will start jdb in a detached screen and name the session for the screen autojdb. You can see the list of your screens using screen -ls. When you want to access the debugger that has been started use screen -r autojdb. Make sure to put the script in your path or give the full path (/home/me/screenjdb below) in your launch option:

java -agentlib:jdwp=transport=dt_socket,address=8000,server=y,onuncaught=y,suspend=n,launch=/home/me/screenjdb MyClass

In my script I also passed -L to screen which logs the session. This will record the session but also let you see any errors that occurred if the attach fails for some reason.




回答2:


Instead of using a debugger and attaching one remotely, why don't you create an uncaught exception handler using Thread.UncaughtExceptionHandler ?

public class ThreadCatch
{
    public static void main(String... args)
    {
        new ThreadCatch().go();
    }

    public void go()
    {
        try {
            Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
                @Override
                public void uncaughtException(Thread t, Throwable e) {
                    System.out.println("Uncaught exception");
                    e.printStackTrace();
                }
            });

            final Thread thread = new Thread(new A());
            thread.start();
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    class A implements Runnable
    {
        int x = 10;

        @Override
        public void run()
        {
            x++;
            ObjectTrackingException obj = new ObjectTrackingException();
            obj.setThrownFrom(this);
            throw obj;
        }
    }
}


class ObjectTrackingException extends RuntimeException
{
    private Object thrownFrom;

    public Object getThrownFrom() {
        return thrownFrom;
    }

    public void setThrownFrom(Object thrownFrom) {
        this.thrownFrom = thrownFrom;
    }
}



来源:https://stackoverflow.com/questions/28528325/attach-jdb-on-uncaught-exception

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!