< prev index next >

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

Print this page
rev 13708 : 8231584: Deadlock with ClassLoader.findLibrary and System.loadLibrary call
Reviewed-by: mchung
   1 /*
   2  * Copyright (c) 2013, 2015, 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


1450                         new SystemClassLoaderAction(scl));
1451                 } catch (PrivilegedActionException pae) {
1452                     oops = pae.getCause();
1453                     if (oops instanceof InvocationTargetException) {
1454                         oops = oops.getCause();
1455                     }
1456                 }
1457                 if (oops != null) {
1458                     if (oops instanceof Error) {
1459                         throw (Error) oops;
1460                     } else {
1461                         // wrap the exception
1462                         throw new Error(oops);
1463                     }
1464                 }
1465             }
1466             sclSet = true;
1467         }
1468     }
1469 











1470     // Returns true if the specified class loader can be found in this class
1471     // loader's delegation chain.
1472     boolean isAncestor(ClassLoader cl) {
1473         ClassLoader acl = this;
1474         do {
1475             acl = acl.parent;
1476             if (cl == acl) {
1477                 return true;
1478             }
1479         } while (acl != null);
1480         return false;
1481     }
1482 
1483     // Tests if class loader access requires "getClassLoader" permission
1484     // check.  A class loader 'from' can access class loader 'to' if
1485     // class loader 'from' is same as class loader 'to' or an ancestor
1486     // of 'to'.  The class loader in a system domain can access
1487     // any class loader.
1488     private static boolean needsClassLoaderPermissionCheck(ClassLoader from,
1489                                                            ClassLoader to)


1792         n = i = 0;
1793         j = ldpath.indexOf(ps);
1794         while (j >= 0) {
1795             if (j - i > 0) {
1796                 paths[n++] = ldpath.substring(i, j);
1797             } else if (j - i == 0) {
1798                 paths[n++] = ".";
1799             }
1800             i = j + 1;
1801             j = ldpath.indexOf(ps, i);
1802         }
1803         paths[n] = ldpath.substring(i, ldlen);
1804         return paths;
1805     }
1806 
1807     // Invoked in the java.lang.Runtime class to implement load and loadLibrary.
1808     static void loadLibrary(Class<?> fromClass, String name,
1809                             boolean isAbsolute) {
1810         ClassLoader loader =
1811             (fromClass == null) ? null : fromClass.getClassLoader();
1812         if (sys_paths == null) {
1813             usr_paths = initializePath("java.library.path");
1814             sys_paths = initializePath("sun.boot.library.path");
1815         }
1816         if (isAbsolute) {
1817             if (loadLibrary0(fromClass, new File(name))) {
1818                 return;
1819             }
1820             throw new UnsatisfiedLinkError("Can't load library: " + name);
1821         }
1822         if (loader != null) {
1823             String libfilename = loader.findLibrary(name);
1824             if (libfilename != null) {
1825                 File libfile = new File(libfilename);
1826                 if (!libfile.isAbsolute()) {
1827                     throw new UnsatisfiedLinkError(
1828     "ClassLoader.findLibrary failed to return an absolute path: " + libfilename);
1829                 }
1830                 if (loadLibrary0(fromClass, libfile)) {
1831                     return;
1832                 }
1833                 throw new UnsatisfiedLinkError("Can't load " + libfilename);
1834             }
1835         }


1885         ClassLoader loader =
1886             (fromClass == null) ? null : fromClass.getClassLoader();
1887         Vector<NativeLibrary> libs =
1888             loader != null ? loader.nativeLibraries : systemNativeLibraries;
1889         synchronized (libs) {
1890             int size = libs.size();
1891             for (int i = 0; i < size; i++) {
1892                 NativeLibrary lib = libs.elementAt(i);
1893                 if (name.equals(lib.name)) {
1894                     return true;
1895                 }
1896             }
1897 
1898             synchronized (loadedLibraryNames) {
1899                 if (loadedLibraryNames.contains(name)) {
1900                     throw new UnsatisfiedLinkError
1901                         ("Native Library " +
1902                          name +
1903                          " already loaded in another classloader");
1904                 }
1905                 /* If the library is being loaded (must be by the same thread,
1906                  * because Runtime.load and Runtime.loadLibrary are
1907                  * synchronous). The reason is can occur is that the JNI_OnLoad
1908                  * function can cause another loadLibrary invocation.
1909                  *
1910                  * Thus we can use a static stack to hold the list of libraries
1911                  * we are loading.


1912                  *
1913                  * If there is a pending load operation for the library, we
1914                  * immediately return success; otherwise, we raise
1915                  * UnsatisfiedLinkError.
1916                  */
1917                 int n = nativeLibraryContext.size();
1918                 for (int i = 0; i < n; i++) {
1919                     NativeLibrary lib = nativeLibraryContext.elementAt(i);
1920                     if (name.equals(lib.name)) {
1921                         if (loader == lib.fromClass.getClassLoader()) {
1922                             return true;
1923                         } else {
1924                             throw new UnsatisfiedLinkError
1925                                 ("Native Library " +
1926                                  name +
1927                                  " is being loaded in another classloader");
1928                         }
1929                     }
1930                 }
1931                 NativeLibrary lib = new NativeLibrary(fromClass, name, isBuiltin);


   1 /*
   2  * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2019, Azul Systems, Inc. All rights reserved.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.  Oracle designates this
   9  * particular file as subject to the "Classpath" exception as provided
  10  * by Oracle in the LICENSE file that accompanied this code.
  11  *
  12  * This code is distributed in the hope that it will be useful, but WITHOUT
  13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15  * version 2 for more details (a copy is included in the LICENSE file that
  16  * accompanied this code).
  17  *
  18  * You should have received a copy of the GNU General Public License version
  19  * 2 along with this work; if not, write to the Free Software Foundation,
  20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  21  *
  22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  23  * or visit www.oracle.com if you need additional information or have any


1451                         new SystemClassLoaderAction(scl));
1452                 } catch (PrivilegedActionException pae) {
1453                     oops = pae.getCause();
1454                     if (oops instanceof InvocationTargetException) {
1455                         oops = oops.getCause();
1456                     }
1457                 }
1458                 if (oops != null) {
1459                     if (oops instanceof Error) {
1460                         throw (Error) oops;
1461                     } else {
1462                         // wrap the exception
1463                         throw new Error(oops);
1464                     }
1465                 }
1466             }
1467             sclSet = true;
1468         }
1469     }
1470 
1471     /*
1472      * Initialize default paths for native libraries search.
1473      * Must be done early as JDK may load libraries during bootstrap.
1474      *
1475      * @see java.lang.System#initPhase1
1476      */
1477     static void initLibraryPaths() {
1478         usr_paths = initializePath("java.library.path");
1479         sys_paths = initializePath("sun.boot.library.path");
1480     }
1481 
1482     // Returns true if the specified class loader can be found in this class
1483     // loader's delegation chain.
1484     boolean isAncestor(ClassLoader cl) {
1485         ClassLoader acl = this;
1486         do {
1487             acl = acl.parent;
1488             if (cl == acl) {
1489                 return true;
1490             }
1491         } while (acl != null);
1492         return false;
1493     }
1494 
1495     // Tests if class loader access requires "getClassLoader" permission
1496     // check.  A class loader 'from' can access class loader 'to' if
1497     // class loader 'from' is same as class loader 'to' or an ancestor
1498     // of 'to'.  The class loader in a system domain can access
1499     // any class loader.
1500     private static boolean needsClassLoaderPermissionCheck(ClassLoader from,
1501                                                            ClassLoader to)


1804         n = i = 0;
1805         j = ldpath.indexOf(ps);
1806         while (j >= 0) {
1807             if (j - i > 0) {
1808                 paths[n++] = ldpath.substring(i, j);
1809             } else if (j - i == 0) {
1810                 paths[n++] = ".";
1811             }
1812             i = j + 1;
1813             j = ldpath.indexOf(ps, i);
1814         }
1815         paths[n] = ldpath.substring(i, ldlen);
1816         return paths;
1817     }
1818 
1819     // Invoked in the java.lang.Runtime class to implement load and loadLibrary.
1820     static void loadLibrary(Class<?> fromClass, String name,
1821                             boolean isAbsolute) {
1822         ClassLoader loader =
1823             (fromClass == null) ? null : fromClass.getClassLoader();
1824         assert sys_paths != null : "should be initialized at this point";
1825         assert usr_paths != null : "should be initialized at this point";
1826 

1827         if (isAbsolute) {
1828             if (loadLibrary0(fromClass, new File(name))) {
1829                 return;
1830             }
1831             throw new UnsatisfiedLinkError("Can't load library: " + name);
1832         }
1833         if (loader != null) {
1834             String libfilename = loader.findLibrary(name);
1835             if (libfilename != null) {
1836                 File libfile = new File(libfilename);
1837                 if (!libfile.isAbsolute()) {
1838                     throw new UnsatisfiedLinkError(
1839     "ClassLoader.findLibrary failed to return an absolute path: " + libfilename);
1840                 }
1841                 if (loadLibrary0(fromClass, libfile)) {
1842                     return;
1843                 }
1844                 throw new UnsatisfiedLinkError("Can't load " + libfilename);
1845             }
1846         }


1896         ClassLoader loader =
1897             (fromClass == null) ? null : fromClass.getClassLoader();
1898         Vector<NativeLibrary> libs =
1899             loader != null ? loader.nativeLibraries : systemNativeLibraries;
1900         synchronized (libs) {
1901             int size = libs.size();
1902             for (int i = 0; i < size; i++) {
1903                 NativeLibrary lib = libs.elementAt(i);
1904                 if (name.equals(lib.name)) {
1905                     return true;
1906                 }
1907             }
1908 
1909             synchronized (loadedLibraryNames) {
1910                 if (loadedLibraryNames.contains(name)) {
1911                     throw new UnsatisfiedLinkError
1912                         ("Native Library " +
1913                          name +
1914                          " already loaded in another classloader");
1915                 }
1916                 /*
1917                  * When a library is being loaded, JNI_OnLoad function can cause
1918                  * another loadLibrary invocation that should succeed.

1919                  *
1920                  * We use a static stack to hold the list of libraries we are
1921                  * loading because this can happen only when called by the
1922                  * same thread because Runtime.load and Runtime.loadLibrary
1923                  * are synchronous.
1924                  *
1925                  * If there is a pending load operation for the library, we
1926                  * immediately return success; otherwise, we raise
1927                  * UnsatisfiedLinkError.
1928                  */
1929                 int n = nativeLibraryContext.size();
1930                 for (int i = 0; i < n; i++) {
1931                     NativeLibrary lib = nativeLibraryContext.elementAt(i);
1932                     if (name.equals(lib.name)) {
1933                         if (loader == lib.fromClass.getClassLoader()) {
1934                             return true;
1935                         } else {
1936                             throw new UnsatisfiedLinkError
1937                                 ("Native Library " +
1938                                  name +
1939                                  " is being loaded in another classloader");
1940                         }
1941                     }
1942                 }
1943                 NativeLibrary lib = new NativeLibrary(fromClass, name, isBuiltin);


< prev index next >