有没有办法缩短控制台Java应用程序的启动时间?

8

我注意到在我的机器上,Java最小控制台应用程序的启动时间略高于100毫秒,而等效的C应用程序只需要1毫秒。虽然在大多数情况下这不是问题,但我想找出是否有一种方法可以减少这个时间,因为我需要编写一个将被执行多次的应用程序(比如在bash脚本循环内)。


请确保使用-client。以下是有关编程的内容:如何减少Scala/Java启动开销 - sfussenegger
谢谢提供的链接。不幸的是,-client 对我的机器启动时间没有任何影响。 - vitaut
4个回答

3
以下是我使用的解决方案的一些细节。
从这个芝麻绿豆的程序(HelloWorld.java)开始,它大约需要100毫秒才能执行:
class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, world!");
   }
}

$ javac HelloWorld.java
$ time java HelloWorld
Hello, world!

real    0m0.109s
user    0m0.030s
sys     0m0.030s

我将其转换为一个简单的服务器:
import java.io.*;
import java.net.*;

class HelloWorldThread extends Thread {
    private Socket socket;

    public HelloWorldThread(Socket s) {
        super("HelloWorldThread");
        socket = s;
    }

    public void run() {
        try {
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            out.println("Hello, world!");
            out.close();
            socket.close();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class HelloWorld {
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(30281);
            while (true)
                new HelloWorldThread(serverSocket.accept()).start();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
}

只需启动一次并使用netcat与其连接(感谢PeterMmm提供的想法),执行时间仅为3毫秒:

$ javac HelloWorld.java
$ java HelloWorld &
$ time nc localhost 30281
Hello, world!

real    0m0.003s
user    0m0.000s
sys     0m0.000s

3
您在寻找Java的“致命弱点”。实际上,这方面并没有太多可以做的。最新的Java版本将是最高效的,他们已经为此问题工作了多年(链接1)
无论如何,运行相同的程序多次后,您会注意到在第一次启动后,下一次启动速度更快。我认为这是由于操作系统缓存机制所导致的。
唯一真正改善性能的方法是让您的应用程序在后台运行,并通过Web服务与您的应用程序通信(这就是Servlet容器的全部内容)。
100毫秒听起来不算太多,但在某些情况下可能是无法接受的。

很遗憾,Java Quick Starter 只适用于 Windows。 - vitaut
确实,随着后续运行的改进,启动时间有所提高,但100毫秒是良好的改进时间。我正在考虑在第一次运行时启动某种后台进程,并在后续运行中使用它,但还不确定如何实现。 - vitaut
1
您可以编写一个应用程序,侦听TCP套接字,接收一些命令并将结果作为纯文本返回。使用netcat从脚本连接到套接字即可(几乎就是这样)。 - PeterMmm

2

使用GCJ将您的代码编译为本地代码。这会有所帮助,但不要期望太多。


+1 是因为它确实提高了2.5倍的速度。然而,它仍需要40毫秒,这比netcat解决方案慢了约10倍。 - vitaut

1

也许Java并不是最适合这项工作的工具?仅出于性能原因而使用客户端-服务器方法似乎是一个非常糟糕的想法。您会引入额外的复杂性和故障点。如果服务器崩溃或TCP端口已被占用,怎么办?


如果我可以使用另一种语言,我就不会问这个问题了。Java是必须的。但你说得对,还有额外的复杂性,尽管我很惊讶在Java中实现服务器是多么容易。 - vitaut
如果语言无法更改,我建议使用命名管道而不是TCP套接字。这是一种更简单和更可靠的解决方案。 - Jacek Ławrynowicz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接