src/share/classes/java/lang/ClassLoader.java

Print this page


   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;