简体   繁体   中英

Restore stack trace from string

I am implementing an Android app and save exceptions to the SQLite database when they occure, because the user should not be interrupted in his work. Later on when he decides to send the exception to the developer console, I would like to throw the exception like this:

throw new Exception("Name of the exception");

Is there any way to rebuild the stack trace again on base of the string I saved before?

It is not possible to do using only strings. However if you can serialize the exception into a byte array, and store that as a blob in your SQLite DB. Click here to learn how to add blob data to a SQLite db.

Here is how to convert exceptions to and from byte arrays:

public class Main {

    public static void main(String args[]){
        try{
            throw new Exception("There is an error here!");
        }catch(Exception e){
            e.printStackTrace();
            byte[] arr = convertExceptionToBlob(e); //save this as a BLOB in your database.
            Exception retrieved = getExceptionFromBlob(arr);
            retrieved.printStackTrace();

        }

    }

    public static byte[] convertExceptionToBlob(Exception e){
        try(ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutput out = new ObjectOutputStream(bos)){
            out.writeObject(e);
            return bos.toByteArray(); 
        }catch(Exception ex){
            return new byte[]{};
        }
    }

    public static Exception getExceptionFromBlob(byte[] arr){
        try (ByteArrayInputStream bis = new ByteArrayInputStream(arr);
            ObjectInput in = new ObjectInputStream(bis)) {
            return (Exception)in.readObject();
        }catch(Exception ex){
            return new Exception(ex.getMessage());
        }
    }
}

Thank you Dylan for your answer! I discussed it with my colleagues and we found another solution:

Our idea was to split up the stack trace elements and to merge it to a string:

    StringBuilder stackTraceStringBuilder = new StringBuilder();
    for (StackTraceElement stackTraceElement : exception.getStackTrace())
        stackTraceStringBuilder.append(String.format("%s|%s|%s|%d\n", stackTraceElement.getClassName(), stackTraceElement.getMethodName(), stackTraceElement.getFileName(), stackTraceElement.getLineNumber()));
    this.stackTrace = stackTraceStringBuilder.toString();

To restore the string to a stack trace element is quite simple:

    RuntimeException runtimeException = new RuntimeException(message);
    String[] stackTraceRows = stackTrace.split("\n");
    StackTraceElement[] stackTraceElements = new StackTraceElement[stackTraceRows.length];
    for (int i = 0; i < stackTraceRows.length; i++) {
        String[] stackTraceRow = stackTraceRows[i].split("\\|");
        stackTraceElements[i] = new StackTraceElement(stackTraceRow[0], stackTraceRow[1], stackTraceRow[2], Integer.parseInt(stackTraceRow[3]));
    }
    runtimeException.setStackTrace(stackTraceElements);

Anyway, the solution of Dylan looks better, but I dont want to withhold this option.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM