【问题标题】:java process is frozen(?) on linuxjava进程在Linux上被冻结(?)
【发布时间】:2009-12-09 08:01:25
【问题描述】:

这是我关于 S.O. 的第一个问题
我有一个非常奇怪的问题。
下面是我的问题...

我编写了非常简单的方法,将一些文本写入文件。
当然在我的机器上效果很好(XP, 4CPU, jdk1.5.0_17[SUN])
但它有时会在运行服务器上冻结
(Linux Accounting240 2.4.20-8smp,4CPU,jdk1.5.0_22[SUN])。

kill -3 不起作用。
ctrl + \ 不起作用。

所以,我不能给你看线程转储。

它冻结得很好.. 当我只是用这种方法写一些 Thread.sleep(XX) 时,问题就解决了(?)...
sleep(XX) break... 今天又发生了 Thread.sleep(XX) )...

你知道这个问题吗? 你有一些解决方案吗? 谢谢。 :-)

附言
linux 发行版:Red Hat Linux 3.2.2-5
命令:java -cp。

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

public class T {
private BufferedWriter writer = null;

private void log(String log) {
    try {
        if (writer == null) {
            File logFile = new File("test.log");
            writer = new BufferedWriter(new OutputStreamWriter(
                    new FileOutputStream(logFile, true)));
        }
        writer.write(new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss] ")
                .format(new Date()));
        writer.write("[" + log + "]" + "\n");
        writer.flush();

         /*
                         *  this is ad hoc solution ???
                         */
        //Thread.sleep(10);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {         
    }

}

public void test() {
    long startTime = System.currentTimeMillis();

    while (true) {
        log(String.valueOf(System.currentTimeMillis()));
        System.out.println(System.currentTimeMillis());
        try {
            //Thread.sleep((int) (Math.random() * 100));
        } catch (Exception e) {
            break;
        }

        if (System.currentTimeMillis() - startTime > 1000 * 5) {
            break;
        }
    }

    if (writer != null) {
        try {
            writer.close();
        } catch (Exception e) {
        }
    }
    System.out.println("OK");
}

public static void main(String[] args) {
    new T().test();
}
}

【问题讨论】:

  • 如果您想进行日志记录,我强烈建议您使用现有的日志记录框架,如果这是您可以选择的选项。想到 log4j 或 slf4j。
  • 或 java.util.logging。随您的 JDK 一起提供。
  • 在我的双核 Ubuntu AMD64 机器(Sun 的“服务器”虚拟机)上运行 5 次后无法重现。 java version "1.6.0_0" OpenJDK Runtime Environment (IcedTea6 1.6.1) (6b16-1.6.1-3ubuntu1) OpenJDK 64-Bit Server VM (build 14.0-b16, mixed mode)
  • 是的.. 我绝对同意你所说的。但是我的最终程序的功能非常小,将文本写入数据文件和记录。就该程序可以将文本写入文件而言,它可能会再次发生。所以,我很担心这个。谢谢,布赫。
  • 运行服务器上的JDK版本为Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_22-b03) Java HotSpot(TM) Server VM (build 1.5.0_22-b03, 混合模式) )。我执行 java -client -cp 。 T 没有 Thread.sleep 代码,问题就消失了......我根本无法理解。嗯……

标签: java linux file multiprocessor


【解决方案1】:

如果 JVM 对 kill -3 没有响应,则不是您的程序,而是 JVM 出现故障,这是错误的,需要向 Sun 报告错误。

我注意到您正在运行 2.4.20-8smp 内核。这不是当前开源 Linux 发行版的典型内核,因此我建议您查看 http://java.sun.com/j2se/1.5.0/system-configurations.html 以了解您是否正在部署到受支持的配置。如果没有,你应该让负责的人知道这一点!

【讨论】:

    【解决方案2】:

    第一步是获取程序“冻结”时所在位置的线程转储。如果这是在 Java 6 上,您可以默认将 JVisualVM 或 JConsole 连接到它,并从那里获取所有线程的堆栈跟踪。由于它是 Java 5,您应该能够使用 jstack 命令来获取线程转储(或者您可以使用命令行选项启用 JMX 以附加上述工具,但我认为这不值得案子)。在所有情况下,从启动应用程序的控制台按 Ctrl-Break 也可能会产生线程转储,具体取决于环境。

    每隔几秒钟执行几次,然后比较线程转储。如果它们总是相同,那么看起来您的应用程序已死锁;转储的第一行将准确显示线程阻塞的位置(这将提供一个很好的线索,当您查看该代码行时,它们被阻塞在哪些资源上)。

    另一方面,如果线程转储不时更改,则程序并未严格死锁,但看起来它正在无限循环中运行 - 可能您的循环条件之一未正确声明,因此线程永远不会退出或其他什么那种。同样,查看线程转储集以了解每个线程在哪个代码区域循环,这将使您了解永远不会评估退出条件的循环条件。

    如果此分析中问题不明显,请发回转储文件,因为这将有助于人们调试您的上述代码。

    【讨论】:

    • 是啊~~我这次遇到了这个问题,有机会搜索和挖掘很多解决问题的方法。线程转储,JConsole 就像你说的那样。这些是我尝试的方法。首先,线程转储案例,Ctrl + \(Linux) 不起作用。并且 kill -3 PID 也不起作用。但是我可以通过这些方式看到其他java进程的线程转储。这有点奇怪。其次,JConsole 成功连接到冻结的 java 进程,但在 Jconsole UI 上没有显示监控数据。而且我可以看到其他java进程的彩色图形监控数据。啊~~~~现在,我没有什么要弄清楚的了。
    【解决方案3】:

    我认为这是一个竞争条件。 while(true) 将强制 linux 上的 VM 连续写入和刷新,Linux 内核 VM 将尝试拦截这些调用并缓冲写入。这将使进程在等待系统调用完成时自旋;同时,它会被调度程序拾取并分配给另一个 CPU(我在这里可能是错的,tho)。新的 CPU 会尝试获取资源上的锁,一切都会导致死锁。

    这可能是其他问题出现的迹象。我建议:

    • 首先,为了清楚起见:将文件创建移到log() 方法之外。这就是构造函数的用途。

    • 其次,您为什么要尝试写入这样的文件?你确定你的程序逻辑一开始就有意义吗?您是否宁愿将日志消息写入容器(例如 ArrayList)并每隔 XX 秒将其转储到单独线程中的磁盘?现在,您将日志记录能力限制为磁盘速度:您可能希望避免这种情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-19
      • 2012-08-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多