1 /*
2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
1723 * Every classloader contains a vector of loaded native libraries in the
1724 * private field <tt>nativeLibraries</tt>. The native libraries loaded
1725 * into the system are entered into the <tt>systemNativeLibraries</tt>
1726 * vector.
1727 *
1728 * <p> Every native library requires a particular version of JNI. This is
1729 * denoted by the private <tt>jniVersion</tt> field. This field is set by
1730 * the VM when it loads the library, and used by the VM to pass the correct
1731 * version of JNI to the native methods. </p>
1732 *
1733 * @see ClassLoader
1734 * @since 1.2
1735 */
1736 static class NativeLibrary {
1737 // opaque handle to native library, used in native code.
1738 long handle;
1739 // the version of JNI environment the native library requires.
1740 private int jniVersion;
1741 // the class from which the library is loaded, also indicates
1742 // the loader this native library belongs.
1743 private Class<?> fromClass;
1744 // the canonicalized name of the native library.
1745 String name;
1746
1747 native void load(String name);
1748 native long find(String name);
1749 native void unload();
1750
1751 public NativeLibrary(Class<?> fromClass, String name) {
1752 this.name = name;
1753 this.fromClass = fromClass;
1754 }
1755
1756 protected void finalize() {
1757 synchronized (loadedLibraryNames) {
1758 if (fromClass.getClassLoader() != null && handle != 0) {
1759 /* remove the native library name */
1760 int size = loadedLibraryNames.size();
1761 for (int i = 0; i < size; i++) {
1762 if (name.equals(loadedLibraryNames.elementAt(i))) {
1763 loadedLibraryNames.removeElementAt(i);
1764 break;
1765 }
1766 }
1767 /* unload the library. */
1768 ClassLoader.nativeLibraryContext.push(this);
1769 try {
1770 unload();
1771 } finally {
1772 ClassLoader.nativeLibraryContext.pop();
1773 }
1774 }
1775 }
1776 }
1777 // Invoked in the VM to determine the context class in
1778 // JNI_Load/JNI_Unload
1779 static Class<?> getFromClass() {
1780 return ClassLoader.nativeLibraryContext.peek().fromClass;
1781 }
1782 }
1783
1784 // All native library names we've loaded.
1785 private static Vector<String> loadedLibraryNames = new Vector<>();
1786
1787 // Native libraries belonging to system classes.
1788 private static Vector<NativeLibrary> systemNativeLibraries
1789 = new Vector<>();
1790
1870 }
1871 }
1872 if (loader != null) {
1873 for (int i = 0 ; i < usr_paths.length ; i++) {
1874 File libfile = new File(usr_paths[i],
1875 System.mapLibraryName(name));
1876 if (loadLibrary0(fromClass, libfile)) {
1877 return;
1878 }
1879 libfile = ClassLoaderHelper.mapAlternativeName(libfile);
1880 if (libfile != null && loadLibrary0(fromClass, libfile)) {
1881 return;
1882 }
1883 }
1884 }
1885 // Oops, it failed
1886 throw new UnsatisfiedLinkError("no " + name + " in java.library.path");
1887 }
1888
1889 private static boolean loadLibrary0(Class<?> fromClass, final File file) {
1890 boolean exists = AccessController.doPrivileged(
1891 new PrivilegedAction<Object>() {
1892 public Object run() {
1893 return file.exists() ? Boolean.TRUE : null;
1894 }})
1895 != null;
1896 if (!exists) {
1897 return false;
1898 }
1899 String name;
1900 try {
1901 name = file.getCanonicalPath();
1902 } catch (IOException e) {
1903 return false;
1904 }
1905 ClassLoader loader =
1906 (fromClass == null) ? null : fromClass.getClassLoader();
1907 Vector<NativeLibrary> libs =
1908 loader != null ? loader.nativeLibraries : systemNativeLibraries;
1909 synchronized (libs) {
1910 int size = libs.size();
1911 for (int i = 0; i < size; i++) {
1912 NativeLibrary lib = libs.elementAt(i);
1913 if (name.equals(lib.name)) {
1914 return true;
1915 }
1916 }
1917
1918 synchronized (loadedLibraryNames) {
1919 if (loadedLibraryNames.contains(name)) {
1920 throw new UnsatisfiedLinkError
1921 ("Native Library " +
1922 name +
1923 " already loaded in another classloader");
1924 }
1931 * we are loading.
1932 *
1933 * If there is a pending load operation for the library, we
1934 * immediately return success; otherwise, we raise
1935 * UnsatisfiedLinkError.
1936 */
1937 int n = nativeLibraryContext.size();
1938 for (int i = 0; i < n; i++) {
1939 NativeLibrary lib = nativeLibraryContext.elementAt(i);
1940 if (name.equals(lib.name)) {
1941 if (loader == lib.fromClass.getClassLoader()) {
1942 return true;
1943 } else {
1944 throw new UnsatisfiedLinkError
1945 ("Native Library " +
1946 name +
1947 " is being loaded in another classloader");
1948 }
1949 }
1950 }
1951 NativeLibrary lib = new NativeLibrary(fromClass, name);
1952 nativeLibraryContext.push(lib);
1953 try {
1954 lib.load(name);
1955 } finally {
1956 nativeLibraryContext.pop();
1957 }
1958 if (lib.handle != 0) {
1959 loadedLibraryNames.addElement(name);
1960 libs.addElement(lib);
1961 return true;
1962 }
1963 return false;
1964 }
1965 }
1966 }
1967
1968 // Invoked in the VM class linking code.
1969 static long findNative(ClassLoader loader, String name) {
1970 Vector<NativeLibrary> libs =
1971 loader != null ? loader.nativeLibraries : systemNativeLibraries;
1972 synchronized (libs) {
1973 int size = libs.size();
1974 for (int i = 0; i < size; i++) {
1975 NativeLibrary lib = libs.elementAt(i);
1976 long entry = lib.find(name);
1977 if (entry != 0)
1978 return entry;
|
1 /*
2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
1723 * Every classloader contains a vector of loaded native libraries in the
1724 * private field <tt>nativeLibraries</tt>. The native libraries loaded
1725 * into the system are entered into the <tt>systemNativeLibraries</tt>
1726 * vector.
1727 *
1728 * <p> Every native library requires a particular version of JNI. This is
1729 * denoted by the private <tt>jniVersion</tt> field. This field is set by
1730 * the VM when it loads the library, and used by the VM to pass the correct
1731 * version of JNI to the native methods. </p>
1732 *
1733 * @see ClassLoader
1734 * @since 1.2
1735 */
1736 static class NativeLibrary {
1737 // opaque handle to native library, used in native code.
1738 long handle;
1739 // the version of JNI environment the native library requires.
1740 private int jniVersion;
1741 // the class from which the library is loaded, also indicates
1742 // the loader this native library belongs.
1743 private final Class<?> fromClass;
1744 // the canonicalized name of the native library.
1745 // or static library name
1746 String name;
1747 // Indicates if the native library is linked into the VM
1748 boolean isBuiltin;
1749 // Indicates if the native library is loaded
1750 boolean loaded;
1751 native void load(String name, boolean isBuiltin);
1752
1753 native long find(String name);
1754 native void unload(String name, boolean isBuiltin);
1755 static native String findBuiltinLib(String name);
1756
1757 public NativeLibrary(Class<?> fromClass, String name, boolean isBuiltin) {
1758 this.name = name;
1759 this.fromClass = fromClass;
1760 this.isBuiltin = isBuiltin;
1761 }
1762
1763 protected void finalize() {
1764 synchronized (loadedLibraryNames) {
1765 if (fromClass.getClassLoader() != null && loaded) {
1766 /* remove the native library name */
1767 int size = loadedLibraryNames.size();
1768 for (int i = 0; i < size; i++) {
1769 if (name.equals(loadedLibraryNames.elementAt(i))) {
1770 loadedLibraryNames.removeElementAt(i);
1771 break;
1772 }
1773 }
1774 /* unload the library. */
1775 ClassLoader.nativeLibraryContext.push(this);
1776 try {
1777 unload(name, isBuiltin);
1778 } finally {
1779 ClassLoader.nativeLibraryContext.pop();
1780 }
1781 }
1782 }
1783 }
1784 // Invoked in the VM to determine the context class in
1785 // JNI_Load/JNI_Unload
1786 static Class<?> getFromClass() {
1787 return ClassLoader.nativeLibraryContext.peek().fromClass;
1788 }
1789 }
1790
1791 // All native library names we've loaded.
1792 private static Vector<String> loadedLibraryNames = new Vector<>();
1793
1794 // Native libraries belonging to system classes.
1795 private static Vector<NativeLibrary> systemNativeLibraries
1796 = new Vector<>();
1797
1877 }
1878 }
1879 if (loader != null) {
1880 for (int i = 0 ; i < usr_paths.length ; i++) {
1881 File libfile = new File(usr_paths[i],
1882 System.mapLibraryName(name));
1883 if (loadLibrary0(fromClass, libfile)) {
1884 return;
1885 }
1886 libfile = ClassLoaderHelper.mapAlternativeName(libfile);
1887 if (libfile != null && loadLibrary0(fromClass, libfile)) {
1888 return;
1889 }
1890 }
1891 }
1892 // Oops, it failed
1893 throw new UnsatisfiedLinkError("no " + name + " in java.library.path");
1894 }
1895
1896 private static boolean loadLibrary0(Class<?> fromClass, final File file) {
1897 // Check to see if we're attempting to access a static library
1898 String name = NativeLibrary.findBuiltinLib(file.getName());
1899 boolean isBuiltin = (name != null);
1900 if (!isBuiltin) {
1901 boolean exists = AccessController.doPrivileged(
1902 new PrivilegedAction<Object>() {
1903 public Object run() {
1904 return file.exists() ? Boolean.TRUE : null;
1905 }})
1906 != null;
1907 if (!exists) {
1908 return false;
1909 }
1910 try {
1911 name = file.getCanonicalPath();
1912 } catch (IOException e) {
1913 return false;
1914 }
1915 }
1916 ClassLoader loader =
1917 (fromClass == null) ? null : fromClass.getClassLoader();
1918 Vector<NativeLibrary> libs =
1919 loader != null ? loader.nativeLibraries : systemNativeLibraries;
1920 synchronized (libs) {
1921 int size = libs.size();
1922 for (int i = 0; i < size; i++) {
1923 NativeLibrary lib = libs.elementAt(i);
1924 if (name.equals(lib.name)) {
1925 return true;
1926 }
1927 }
1928
1929 synchronized (loadedLibraryNames) {
1930 if (loadedLibraryNames.contains(name)) {
1931 throw new UnsatisfiedLinkError
1932 ("Native Library " +
1933 name +
1934 " already loaded in another classloader");
1935 }
1942 * we are loading.
1943 *
1944 * If there is a pending load operation for the library, we
1945 * immediately return success; otherwise, we raise
1946 * UnsatisfiedLinkError.
1947 */
1948 int n = nativeLibraryContext.size();
1949 for (int i = 0; i < n; i++) {
1950 NativeLibrary lib = nativeLibraryContext.elementAt(i);
1951 if (name.equals(lib.name)) {
1952 if (loader == lib.fromClass.getClassLoader()) {
1953 return true;
1954 } else {
1955 throw new UnsatisfiedLinkError
1956 ("Native Library " +
1957 name +
1958 " is being loaded in another classloader");
1959 }
1960 }
1961 }
1962 NativeLibrary lib = new NativeLibrary(fromClass, name, isBuiltin);
1963 nativeLibraryContext.push(lib);
1964 try {
1965 lib.load(name, isBuiltin);
1966 } finally {
1967 nativeLibraryContext.pop();
1968 }
1969 if (lib.loaded) {
1970 loadedLibraryNames.addElement(name);
1971 libs.addElement(lib);
1972 return true;
1973 }
1974 return false;
1975 }
1976 }
1977 }
1978
1979 // Invoked in the VM class linking code.
1980 static long findNative(ClassLoader loader, String name) {
1981 Vector<NativeLibrary> libs =
1982 loader != null ? loader.nativeLibraries : systemNativeLibraries;
1983 synchronized (libs) {
1984 int size = libs.size();
1985 for (int i = 0; i < size; i++) {
1986 NativeLibrary lib = libs.elementAt(i);
1987 long entry = lib.find(name);
1988 if (entry != 0)
1989 return entry;
|