1 /*
2  * Copyright Amazon.com Inc. 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.
9  *
10  * This code is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * version 2 for more details (a copy is included in the LICENSE file that
14  * accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License version
17  * 2 along with this work; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21  * or visit www.oracle.com if you need additional information or have any
22  * questions.
23  */
24 
25 /**
26  * @test
27  * @bug 8231584
28  * @library /test/lib
29  * @run main/othervm LoadLibraryTest
30  */
31 
32 import java.nio.file.FileSystems;
33 import java.nio.file.Files;
34 import java.nio.file.Paths;
35 import java.nio.file.Path;
36 import java.net.MalformedURLException;
37 import java.net.URLClassLoader;
38 import java.net.URL;
39 
40 import jdk.test.lib.compiler.CompilerUtils;
41 
42 public class LoadLibraryTest {
43     static Thread thread1 = null;
44     static Thread thread2 = null;
45 
46     static volatile boolean thread1Ready = false;
47 
48     private static final String TEST_SRC = System.getProperty("test.src");
49     private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
50     private static final Path CLS_DIR = Paths.get("classes");
51 
52     static TestClassLoader loader;
someLibLoad()53     static void someLibLoad() {
54         try {
55 /*
56             FileSystems.getDefault();
57 
58             // jdk/jdk: loads directly from Bootstrap Classloader (doesn't take lock on Runtime)
59             java.net.NetworkInterface.getNetworkInterfaces();
60 
61 */
62             Class c = Class.forName("Target2", true, loader);
63         } catch (Exception e) {
64             throw new RuntimeException(e);
65         }
66     }
67 
68     static class TestClassLoader extends URLClassLoader {
69         boolean passed = false;
70 
passed()71         public boolean passed() {
72             return passed;
73         }
74 
TestClassLoader()75         TestClassLoader() throws MalformedURLException {
76             super(new URL[] { new URL("file://" + CLS_DIR.toAbsolutePath().toString() + '/') });
77         }
78 
findLibrary(String name)79         public String findLibrary(String name) {
80             System.out.println("findLibrary " + name);
81 
82             if ("someLibrary".equals(name)) {
83                 try {
84                     synchronized(thread1) {
85                         while(!thread1Ready) {
86                             thread1.wait();
87                         }
88                         thread1.notifyAll();
89                     }
90 
91                     Thread.sleep(10000);
92 
93                     System.out.println("Thread2 load");
94                     someLibLoad();
95 
96                     // no deadlock happened
97                     passed = true;
98                 } catch (Exception e) {
99                     throw new RuntimeException(e);
100                 }
101                 return null;
102             }
103 
104             return super.findLibrary(name);
105         }
106     }
107 
108 
main(String[] args)109     public static void main(String[] args) throws Exception {
110         loader = new TestClassLoader();
111 
112         if (!CompilerUtils.compile(SRC_DIR, CLS_DIR)) {
113             throw new Exception("Can't compile");
114         }
115 
116         thread1 = new Thread() {
117             public void run() {
118                 try {
119                     synchronized(this) {
120                         thread1Ready = true;
121                         thread1.notifyAll();
122                         thread1.wait();
123                     }
124                 } catch(InterruptedException e) {
125                     throw new RuntimeException(e);
126                 }
127 
128                 System.out.println("Thread1 load");
129                 someLibLoad();
130             };
131         };
132 
133         thread2 = new Thread() {
134             public void run() {
135                 try {
136                     Class c = Class.forName("Target", true, loader);
137                     System.out.println(c);
138                 } catch (Exception e) {
139                     throw new RuntimeException(e);
140                 }
141             };
142         };
143 
144         thread1.setDaemon(true);
145         thread2.setDaemon(true);
146 
147         thread1.start();
148         thread2.start();
149 
150         thread1.join();
151         thread2.join();
152 
153         if (!loader.passed()) {
154             throw new RuntimeException("FAIL");
155         }
156     }
157 }
158