【问题标题】:exit() method entered without exit commandexit() 方法在没有退出命令的情况下进入
【发布时间】:2016-06-11 04:19:07
【问题描述】:

我的处理 3 代码表现出一些奇怪的行为。我定义了一个void exit() 方法,该方法在随机时间执行,而用户实际上没有告诉代码退出。方法如下:

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();
}

如您所见,它所做的唯一一件事就是尝试关闭一个名为 output 的缓冲写入器。冲洗这个作家并不重要,所以现在我只是把它从我的草图中删除。但从长远来看,我很好奇这是怎么发生的。我的代码中没有其他地方是显式调用的退出方法。 IE,代码无法决定退出。只有当用户使用 X 关闭问题时。

注意:我也无法上传此方法所附的整个代码,因为它太长了。我认为也许更好的方式来表达我的问题是这样的:

“嗨,我是一个对退出方法一无所知的菜鸟。无论如何,如果我没有明确调用它或点击退出按钮,是否可以以某种方式调用此方法?”

【问题讨论】:

  • 正在执行的代码是什么?
  • 你覆盖父级的 exit() 方法吗?
  • 您能否提供一个minimal reproducible example 来说明问题?
  • 您不必上传整个代码。正如 Kevin 上面所说:提供一个展示问题的最小、完整和可验证的示例。这并不意味着提供整个代码。
  • @Murenrb 这正是我们要求minimal reproducible example 的原因。您发布的代码远没有足够的信息。任何东西都可以调用它。尝试将堆栈跟踪打印到控制台以跟踪调用它的内容。

标签: processing exit


【解决方案1】:

exit() 方法的开头添加这个。

    new Exception().printStackTrace();

生成的堆栈跟踪应该可以让您弄清楚是什么调用了您的 exit() 方法。

或者,如果您无法调整代码,您可以使用调试器运行应用程序并在 exit() 方法的开头设置断点。


要回答您关于是否有可能的问题,答案取决于您所说的“没有我明确调用”的意思。调用方法的方式有很多种,其中一些非常晦涩难懂;例如

  • 您可以使用反射从声明类中获取exit方法的Method对象,然后对其调用invoke(...)
  • 您可以通过 JNI 或 JNA api 从本机代码调用 Java 方法。
  • 您可以生成包含exit() 调用的Java 源代码,对其进行编译、加载和运行。
  • 您可以使用 BCEL 或类似方法将 exit() 调用插入“无害”方法。

还有……

  • 如果有调试代理连接到 JVM,调试器可以在 JVM 中的某个线程上调用 exit()

【讨论】:

  • 谢谢!我会添加这个,看看发生了什么。显然,总体问题是这种方法比我想象的要复杂!
【解决方案2】:

简而言之,您的问题的答案是肯定的。

同一类加载器中的任何类或层次结构中的任何其他类都可以使用反射动态地找到和调用您的方法。

此外,它具有默认访问权限。所以它可以被同一个包中的任何类静态调用。

【讨论】:

  • 非常感谢您的回答!你能扩展一下吗?你是什​​么意思“使用任何类的反射”或“默认访问”。实现它的正确方法是什么,以免发生这种情况?
【解决方案3】:

@Andres +1,反射是一种可能性。

您是否尝试过在方法上使用断点并查看线程的堆栈跟踪?

我个人不使用断点(只是我的风格),并会尝试以编程方式查看线程。也许下面的一些代码可以帮助您查看线程并了解正在发生的事情:

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");
    }
}

【讨论】:

    【解决方案4】:

    这是特定于处理的事情。

    void exit()是PApplet.java中已经通过处理定义的方法

    reference中所述:

    exit() 不会立即终止,而是会导致草图 在 draw() 完成后退出(或者在 setup() 完成后,如果调用 在 setup() 函数期间)。

    对于 Java 程序员,这与 System.exit() 不同。更远, 不应使用 System.exit(),因为关闭应用程序 在 draw() 运行时可能会导致崩溃(尤其是 P3D)。

    exit() 预计会这样使用:

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

    它在PApplet.java 的一些地方被调用,特别是在handleKeyEvent 中,当按下ESC 或按下⌘w 时关闭草图。

    只需将您的方法重命名为 exit() 以外的其他名称

    【讨论】:

    • 但问题是我需要该方法在退出时运行,而不是在按下特定按钮或其他东西时运行。 IE,我想我想使用 PApplet.java 方法。用户无法在正常操作中关闭代码。但是如果脚本是通过 X 按钮或其他东西关闭的,那么我想确保刷新一个 .csv 编写器。
    猜你喜欢
    • 2013-04-05
    • 1970-01-01
    • 1970-01-01
    • 2011-03-19
    • 2016-04-05
    • 2019-02-25
    • 2021-10-15
    • 2013-01-31
    • 2012-07-15
    相关资源
    最近更新 更多