从 java(runtime.exec)调用 wget 会挂起并将下载限制为特定文件大小(而 curl 则不会)

从 java(runtime.exec)调用 wget 会挂起并将下载限制为特定文件大小(而 curl 则不会)

问题详细信息

我正在尝试从 java 调用 wget 来下载文件,但是我一直遇到一个奇怪的问题,即文件大小受到限制。

例如,发出“wgethttps://speed.hetzner.de/1GB.bin“,我正确地拥有 1GB.bin,文件大小为 1,048,576,000(正好是 1 GB)。但是当从 java 调用相同的命令时,我始终得到大约 40 MB 的文件。

调试

假设你已经安装了 JDK,下面是一个血管内皮生长因子重现此行为:

echo 'class RunCommand {
    public static void main(String[] args) throws Exception {
        String s = "";
        for (int i=0; i < args.length; i++)
            s += (i > 0 ? " " : "") + args[i];
        System.out.println(Runtime.getRuntime().exec(s).waitFor());
    }
}' > RunCommand.java

javac RunCommand.java

java RunCommand wget https://speed.hetzner.de/1GB.bin

我已经在干净的 AWS CentOS 7.6 机器上尝试过此操作:

  • OpenJDK 7
  • OpenJDK 8
  • Oracle JDK 8

我总是得到相同的结果:java 挂起并且文件大小约为 40 MB。

我也尝试过增加堆大小,但-Xms1024m -Xmx1024m没有效果,最后得出结论,堆大小不是问题。

现在,用 curl 再次运行完全相同的操作:

java RunCommand curl https://speed.hetzner.de/1GB.bin -o 1GB.bin

令人惊讶的是,这个方法有效,我成功得到了一个 1GB 的文件!

问题

所以这里有很多问题:

  1. 为什么 Java 在 40 MB 之后会挂起?
  2. 为什么总是正好 40 MB?(grepping 40-XX:+PrintFlagsFinal没有任何线索)
  3. wget 和 curl 命令之间有什么区别,导致一个失败而另一个成功?

答案1

尝试在命令中添加 --quiet ;可能是标准输出已满,因为您没有通过输入流读取它。

这是从 wget 手册中提取的。

    -q
    --quiet
    Turn off Wget’s output.

检查下面的代码片段。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Created on 2/13/2019.
 *
 * @author Julien Saab
 */
public class TestCommand {
    public static void main(String[] args) throws Exception {

        final List<String> commands = new ArrayList<>(Arrays.asList(args));
        commands.add("--quiet");
        final Process process = new ProcessBuilder().command(commands).start();
        final int i = process.waitFor();

        System.out.printf("Process exited with code %1$s\n", i);
    }
}

我尝试过您使用的相同文件,它的大小已超过 41 MB(但我当然没有完全下载它)。

java TestCommand wget https://speed.hetzner.de/1GB.bin

相关内容