From 4895a15a779fab70290b4df3b464d79a14937e28 Mon Sep 17 00:00:00 2001 From: Suchismith Roy Date: Wed, 17 Apr 2024 17:03:40 +0000 Subject: [PATCH] 8319516: AIX System::loadLibrary needs support to load a shared library from an archive object Reviewed-by: mdoerr, mchung --- .../internal/loader/ClassLoaderHelper.java | 77 +++++++++++++++++++ .../aix/LoadAIXLibraryFromArchiveObject.java | 72 +++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 src/java.base/aix/classes/jdk/internal/loader/ClassLoaderHelper.java create mode 100644 test/jdk/java/lang/RuntimeTests/loadLibrary/aix/LoadAIXLibraryFromArchiveObject.java diff --git a/src/java.base/aix/classes/jdk/internal/loader/ClassLoaderHelper.java b/src/java.base/aix/classes/jdk/internal/loader/ClassLoaderHelper.java new file mode 100644 index 00000000000..1e3aa95729a --- /dev/null +++ b/src/java.base/aix/classes/jdk/internal/loader/ClassLoaderHelper.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package jdk.internal.loader; + +import java.io.File; +import java.util.ArrayList; + +class ClassLoaderHelper { + + private ClassLoaderHelper() {} + + /** + * Shared objects may be loaded from .a archive object on AIX and .so may not exist. + * This method returns false so that loading of shared library continues if + * libname.so is not present. + */ + static boolean loadLibraryOnlyIfPresent() { + return false; + } + + /** + * AIX implementation of JVM_LoadLibrary handles the alternate path name mapping. + * If loading of the given library name with ".so" suffix fails, it will attempt + * to load the library of the same name with ".a" suffix as the alternate name. + * This method simply returns null. It could implement the alternate name + * converting ".so" with ".a" suffix but redundant. + */ + static File mapAlternativeName(File lib) { + return null; + } + + /** + * Parse a PATH env variable. + * + * Empty elements will be replaced by dot. + */ + static String[] parsePath(String ldPath) { + char ps = File.pathSeparatorChar; + ArrayList paths = new ArrayList<>(); + int pathStart = 0; + int pathEnd; + while ((pathEnd = ldPath.indexOf(ps, pathStart)) >= 0) { + paths.add((pathStart < pathEnd) ? + ldPath.substring(pathStart, pathEnd) : "."); + pathStart = pathEnd + 1; + } + int ldLen = ldPath.length(); + paths.add((pathStart < ldLen) ? + ldPath.substring(pathStart, ldLen) : "."); + return paths.toArray(new String[paths.size()]); + } +} + diff --git a/test/jdk/java/lang/RuntimeTests/loadLibrary/aix/LoadAIXLibraryFromArchiveObject.java b/test/jdk/java/lang/RuntimeTests/loadLibrary/aix/LoadAIXLibraryFromArchiveObject.java new file mode 100644 index 00000000000..b80bb8e734e --- /dev/null +++ b/test/jdk/java/lang/RuntimeTests/loadLibrary/aix/LoadAIXLibraryFromArchiveObject.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2024, IBM Corporation. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.nio.file.Files; +import java.nio.file.Path; +import jdk.test.lib.process.ProcessTools; + +/** + * @test + * @bug 8319516 + * @summary verify that System.loadLibrary on AIX is able to load libraries from ".a" (archive) file + * @requires os.family == "aix" + * @library /test/lib/ + * @build jdk.test.lib.process.ProcessTools + * @run main/othervm LoadAIXLibraryFromArchiveObject + */ +public class LoadAIXLibraryFromArchiveObject { + + private static final String TEST_LIBRARY_NAME = "foobar"; + // creates a ".a" archive file in a test specific directory and then + // launches a java application passing this directory through "-Djava.library.path". + // the java application then attempts to load the library using System.loadLibrary() + public static void main(String[] args) throws Exception { + String javaHome = System.getProperty("java.home"); + Path libj2pcscSo = Path.of(javaHome).resolve("lib", "libj2pcsc.so"); + if (!Files.exists(libj2pcscSo)) { + throw new AssertionError(libj2pcscSo + " is missing"); + } + String archiveFileName = "lib" + TEST_LIBRARY_NAME + ".a"; + // copy over libj2pcsc.so as an archive file to test specific scratch dir + Path testNativeLibDir = Path.of("native").toAbsolutePath(); + Files.createDirectories(testNativeLibDir); + Path libFooBarArchive = testNativeLibDir.resolve(archiveFileName); + Files.copy(libj2pcscSo, libFooBarArchive); + // launch a java application which calls System.loadLibrary and is passed + // the directory containing the native library archive file, through + // -Djava.library.path + ProcessBuilder processBuilder = ProcessTools.createTestJavaProcessBuilder( + "-Djava.library.path=" + testNativeLibDir, + LoadAIXLibraryFromArchiveObject.LoadLibraryApp.class.getName()); + ProcessTools.executeCommand(processBuilder).shouldHaveExitValue(0); + } + + static class LoadLibraryApp { + public static void main(final String[] args) throws Exception { + System.out.println("attempting to load library " + TEST_LIBRARY_NAME); + System.loadLibrary(TEST_LIBRARY_NAME); + System.out.println(TEST_LIBRARY_NAME + " successfully loaded"); + } + } +} +