【问题标题】:Determine current glibc version from within Java从 Java 中确定当前 glibc 版本
【发布时间】:2019-06-12 06:09:43
【问题描述】:

对于运行在linux系统上的java应用,如何判断glibc的底层版本?

背景:我想在运行时确定是否可以使用 conscrypt,现在这似乎需要 glibc 2.14 (https://github.com/google/conscrypt/pull/589),但我仍然需要优雅地支持在 CentOS 6 或更早版本上运行回退到标准的 Java SSL 代码。不幸的是(至少据我所知)如果 Conscrypt 在较旧的发行版上初始化,则无法捕获并从发生的错误中恢复,但如果我可以确定 glibc 版本,我可以选择是否初始化基于此。

【问题讨论】:

标签: java linux glibc


【解决方案1】:

执行ldd --version 并解析响应以获取版本号的工作示例。

public class Main {

    public static void main(String[] args) throws IOException {
        final ProcessBuilder processBuilder = new ProcessBuilder("/bin/bash").command("ldd --version");
        processBuilder.redirectErrorStream(true);

        final Process process = processBuilder.start();
        final StringBuilder stream = readStream(process.getInputStream());

        final String version = getVersion(stream.toString());

        System.out.println(version);
    }

    /**
     * Read the output stream of the process
     *
     * @param iStream InputStream
     * @return StringBuilder containing the output of the command
     */
    private static StringBuilder readStream(InputStream iStream) throws IOException {
        final StringBuilder builder = new StringBuilder();
        String line;

        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(iStream))) {
            while ((line = bufferedReader.readLine()) != null) {
                builder.append(line);
                builder.append(System.getProperty("line.separator"));
            }
        }

        return builder;
    }

    /**
     * Parse the response for the version number.
     *
     * @param input String response of ldd --version
     * @return String of the version, or null if not found
     */
    private static String getVersion(String input) {
        final Pattern pattern = Pattern.compile("[-+]?[0-9]*\\.?[0-9]+");
        final Matcher matcher = pattern.matcher(input);

        return matcher.find() ? matcher.group() : null;
    }
}

【讨论】:

  • 您是否必须在 Bash 中运行命令而不仅仅是运行命令?通过 Bash 有什么好处?
  • 你为什么关心系统行分隔符?逐行获取文本然后将其重新组合在一起以再次解析它似乎是多余的。使用List<String> 不是更有意义吗?要么直接将输出转储到String,而无需按行进行中间拆分。
  • 当然,公平地说,这主要是我打开的当前项目的复制粘贴和小调整。没有说它已经准备好生产,但它会做 OP 要求的。
【解决方案2】:

我假设您使用一些预构建的二进制文件。您应该能够捕获java.lang.System.load(String) 方法抛出的java.lang.UnsatisfiedLinkError 异常。如果 JNI 共享对象链接正确,动态链接器将检测缺失的符号版本(推测为 GLIBC_2.14),即使惰性绑定处于活动状态。

另外,我在 Conscrypt 中看不到任何会妨碍在 CentOS 6 上构建的东西(对于 C++11 编译器,Developer Toolset software collection)。这有点复杂,但 glibc 2.14 的依赖似乎来自于预构建二进制文件的制作方式,而不是软件本身固有的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-12
    • 2011-03-01
    • 1970-01-01
    • 2018-04-04
    • 2021-02-28
    • 2021-12-31
    • 1970-01-01
    相关资源
    最近更新 更多