Java中一种获取当前系统类型的办法

本文讨论了在Java开发中如何在JDK的Process类中实现自定义pipe通信,以解决跨平台问题。作者在OpenJDK代码中发现了一个针对不同操作系统(如Linux、MacOS、AIX和Windows)的处理方式,展示了Java服务端开发者较少关注的平台特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

工作中遇到需要对JDK的Process类做一些拓展,以便在开AI组的Python工作进程时,从stdout、stderr、stdin三种标准输入输出流外的自定义pipe流传递参数
JDK似乎没给开自定义pipe通信的方式,如果要自定义pipe,就得写native代码,但如此就无法保证跨平台了。最终索性直接将AI组的进程单独容器化,基于HTTP做了通信。
PipedInputStreamPipedOutputStream也只能用于线程间通信。

虽然最后没有成功,但看到了JDK里一些有意思的。

在看Open JDK的Process类代码时,发现一段涉及平台特定功能的代码,这对Java服务端开发者来说很罕见。
对Java服务端开发者来说,JDK&JVM往往会直接确保开发者写的所有代码都是各平台通用的,因此Java开发者一般很少关注平台特性。
比如Windows中开子线程的API CreateThread;Linux、MacOS等类Unix系统API则是pthread_create。JVM直接帮我们屏蔽掉了平台API差异,直接在Java代码里区分平台的情况少之又少。

今天看到的这段代码,说明了如何在Java中获取系统类型。

void initStreams(int[] fds, boolean forceNullOutputStream) throws IOException {
        switch (OperatingSystem.current()) {
            case LINUX:
            case MACOS:
                stdin = (fds[0] == -1) ?
                        ProcessBuilder.NullOutputStream.INSTANCE :
                        new ProcessPipeOutputStream(fds[0]);

                stdout = (fds[1] == -1 || forceNullOutputStream) ?
                         ProcessBuilder.NullInputStream.INSTANCE :
                         new ProcessPipeInputStream(fds[1]);

                stderr = (fds[2] == -1) ?
                         ProcessBuilder.NullInputStream.INSTANCE :
                         new ProcessPipeInputStream(fds[2]);

                ProcessHandleImpl.completion(pid, true).handle((exitcode, throwable) -> {
                    lock.lock();
                    try {
                        this.exitcode = (exitcode == null) ? -1 : exitcode.intValue();
                        this.hasExited = true;
                        condition.signalAll();
                    } finally {
                        lock.unlock();
                    }

                    if (stdout instanceof ProcessPipeInputStream)
                        ((ProcessPipeInputStream) stdout).processExited();

                    if (stderr instanceof ProcessPipeInputStream)
                        ((ProcessPipeInputStream) stderr).processExited();

                    if (stdin instanceof ProcessPipeOutputStream)
                        ((ProcessPipeOutputStream) stdin).processExited();

                    return null;
                });
                break;

            case AIX:
                stdin = (fds[0] == -1) ?
                        ProcessBuilder.NullOutputStream.INSTANCE :
                        new ProcessPipeOutputStream(fds[0]);

                stdout = (fds[1] == -1 || forceNullOutputStream) ?
                         ProcessBuilder.NullInputStream.INSTANCE :
                         new DeferredCloseProcessPipeInputStream(fds[1]);

                stderr = (fds[2] == -1) ?
                         ProcessBuilder.NullInputStream.INSTANCE :
                         new DeferredCloseProcessPipeInputStream(fds[2]);

                ProcessHandleImpl.completion(pid, true).handle((exitcode, throwable) -> {
                    lock.lock();
                    try {
                        this.exitcode = (exitcode == null) ? -1 : exitcode.intValue();
                        this.hasExited = true;
                        condition.signalAll();
                    } finally {
                        lock.unlock();
                    }

                    if (stdout instanceof DeferredCloseProcessPipeInputStream)
                        ((DeferredCloseProcessPipeInputStream) stdout).processExited();

                    if (stderr instanceof DeferredCloseProcessPipeInputStream)
                        ((DeferredCloseProcessPipeInputStream) stderr).processExited();

                    if (stdin instanceof ProcessPipeOutputStream)
                        ((ProcessPipeOutputStream) stdin).processExited();

                    return null;
                });
                break;

            default:
                throw new AssertionError("Unsupported platform: " +
                    OperatingSystem.current());
        }
    }

OperatingSystem.current()方法,获取到当前系统类型的枚举值,OperatingSystem为枚举类型。在我看的OpenJDK 21 代码中,支持四种系统类型Linux、MacOS,Windows,AIX
OperatingSystem.current()方法本身的获取系统类型的方法,是从OperatingSystem.initOS()方法处初始化获得的。

 private static OperatingSystem initOS() {
        return OperatingSystem.valueOf(PlatformProps.CURRENT_OS_STRING.toUpperCase(Locale.ROOT));
}

其中,PlatformProps.CURRENT_OS_STRING,下载JDK时就会根据平台下载到不同文件,一开始就是固定的值。

class PlatformProps {

    // Name of the current OperatingSystem enum as substituted by the build
    static final String CURRENT_OS_STRING = "macos";
    ......
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值