2

I have Processing 3 code that is exhibiting some odd behavior. I have a void exit() method defined that is being executed at random times without the user actually telling the code to exit. Here is the method:

void exit()
{
 println("clearing buffer and closing file");
 if (output != null) {
   print("output is not null");
   try {
     output.close();
   } 
   catch (IOException e) {
     println("Error while closing the writer");
   }
 }
 super.exit();
}

As you can see, the only thing that it does is attempt to close a buffered writer called output. Flushing this writer is not critical, so for now I am just removing it from my sketch. But long term, I am curious how this can be happening. Nowhere else in my code is the exit method explicitly called. IE, the code cannot decide to exit. It is only when the user closes the problem using the X.

Note: I cannot upload the entire code this method is attached too because it is too long. I think perhaps a better way to phrase my questions would be something like:

"Hi, I am a noob that doesn't know anything about the exit method. Is there anyway that this method could somehow get called without me explicitly calling it or hitting the exit button?"

9
  • 2
    What's the code being executed? Commented Jun 6, 2016 at 13:28
  • 2
    Do you override parent exit() method ? Commented Jun 6, 2016 at 13:29
  • 2
    Can you please provide a minimal reproducible example that exhibits the problem? Commented Jun 6, 2016 at 13:30
  • 1
    You don't have to upload the entire code. As Kevin said above: provide a minimal, complete, and verifiable example that exhibits the problem. That doesn't mean to provide the entire code. Commented Jun 6, 2016 at 13:43
  • 1
    @Murenrb That's exactly why we're asking for a minimal reproducible example. The code you posted is nowhere near enough information. Anything could be calling it. Try printing a stack trace to the console to track down what's calling it. Commented Jun 6, 2016 at 14:00

4 Answers 4

3

Add this at the beginning of your exit() method.

    new Exception().printStackTrace();

The resulting stacktrace should allow you to figure out what is calling your exit() method.

Or if you can't tweak the code, you can run the application using a debugger and set a breakpoint at the start of the exit() method.


To answer your question about whether it is possible, the answer depends on what you mean by "without me explicitly calling". There are various ways to call a method, some of which are quite obscure; e.g.

  • You can use reflection to get the Method object for the exit method from the declaring class, and then call invoke(...) on it.
  • You can call a Java method from native code via the JNI or JNA apis.
  • You can generate Java source code that contains an exit() call, compile it, load it, and run it.
  • You can insert an exit() call into an "innocent" method using BCEL or similar.

And ...

  • If there is a debug agent attached to the JVM, the debugger can call exit() on some thread in the JVM.
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! I will add this and see what is going on. Clearly the overall issue is that this method is more complex than I thought!
0

In short, the answer to your question is Yes.

Your method could be found and invoked dynamically using reflection by any class in the same classloader or any other that is below in the hierarchy.

Also, it has a default access. So it could be invoked statically by any class in the same package.

1 Comment

I really appreciate the answer! Can you expand on that? what do you mean "using reflection by any class" or "default access". What is the correct way to implement it such that this does not happen?
0

+1 for @Andres, reflection is one possibility.

Have you tried using a breakpoint on the method and looking at the thread's stacktrace?

Personally I don't use breakpoints (just my style) and would try and look at the thread programmatically. Maybe some of the following code can help you look at the thread and get an idea of what's going on:

public class ThreadUtil {

    /** Blocked constructor **/
    private ThreadUtil() {
    }

    /**
     * Get the stackstrace of the current {@link Thread}.
     * The stacktrace will be returned in the form of a string.
     */
    public static String getStackTrace() {
        return getStackTrace(Thread.currentThread());
    }

    /**
     * Get the stackstrace of a {@link Thread}.
     * The stacktrace will be returned in the form of a string.
     */
    public static String getStackTrace(Thread thread) {
        StringBuilder sb = new StringBuilder();
        StackTraceElement[] currThreadStackTraceElementList = thread.getStackTrace();
        appendStackTrace(sb, currThreadStackTraceElementList);
        return sb.toString();
    }

    public static String getAllStackTraces() {
        StringBuilder sb = new StringBuilder();
        Map<Thread, StackTraceElement[]> threadList = Thread.getAllStackTraces();
        for (StackTraceElement[] currThreadStackTraceElementList : threadList.values()) {
            appendStackTrace(sb, currThreadStackTraceElementList);
        }
        return sb.toString();
    }

    private static void appendStackTrace(StringBuilder sb,
            StackTraceElement[] currThreadStackTraceElementList) {
        sb.append("Thread stack trace: \n");
        for (StackTraceElement currThreadStackTraceElement : currThreadStackTraceElementList) {
            sb.append("\t" + currThreadStackTraceElement + "\n");
        }
        sb.append("\n");
    }
}

Comments

0

It's a Processing-specific thing.

void exit() is a method already defined by processing in PApplet.java

As explained in the reference:

Rather than terminating immediately, exit() will cause the sketch to exit after draw() has completed (or after setup() completes if called during the setup() function).

For Java programmers, this is not the same as System.exit(). Further, System.exit() should not be used because closing out an application while draw() is running may cause a crash (particularly with P3D).

exit() it is expected to be used something like this:

void draw() {
  line(mouseX, mouseY, 50, 50);
}

void mousePressed() {
  exit(); 
}

It is called within PApplet.java in a few places, notably in handleKeyEvent to close the sketch when ESC is pressed, or when ⌘w is pressed.

Just rename your method to something other than exit()

1 Comment

The issue though is that I need the method to run on exit not when a specific button is pressed or something. IE, I think I want to use the PApplet.java method. There is no way for the user to close the code in normal operation. But if the script is closed via the X button or something, then I want to make sure to flush a .csv writer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.