1 /*
2  * Copyright (c) 2018, Amazon 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.
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             System.out.println(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
62 */
63             Class c = Class.forName("Target2", true, loader);
64         } catch (Exception e) {
65             throw new RuntimeException(e);
66         }
67     }
68 
69     static class TestClassLoader extends URLClassLoader {
70         boolean passed = false;
71 
passed()72         public boolean passed() {
73             return passed;
74         }
75 
TestClassLoader()76         TestClassLoader() throws MalformedURLException {
77             super(new URL[] { new URL("file://" + CLS_DIR.toAbsolutePath().toString() + '/') });
78         }
79 
findLibrary(String name)80         public String findLibrary(String name) {
81             System.out.println("findLibrary " + name);
82 
83             if ("someLibrary".equals(name)) {
84                 try {
85                     synchronized(thread1) {
86                         while(!thread1Ready) {
87                             thread1.wait();
88                         }
89                         thread1.notifyAll();
90                     }
91 
92                     Thread.sleep(10000);
93 
94                     System.out.println("Thread2 load");
95                     someLibLoad();
96 
97                     // no deadlock happened
98                     passed = true;
99                 } catch (Exception e) {
100                     throw new RuntimeException(e);
101                 }
102                 return null;
103             }
104 
105             return super.findLibrary(name);
106         }
107     }
108 
109 
main(String[] args)110     public static void main(String[] args) throws Exception {
111         loader = new TestClassLoader();
112 
113         if (!CompilerUtils.compile(SRC_DIR, CLS_DIR)) {
114             throw new Exception("Can't compile");
115         }
116 
117         thread1 = new Thread() {
118             public void run() {
119                 try {
120                     synchronized(this) {
121                         thread1Ready = true;
122                         thread1.notifyAll();
123                         thread1.wait();
124                     }
125                 } catch(InterruptedException e) {
126                     throw new RuntimeException(e);
127                 }
128 
129                 System.out.println("Thread1 load");
130                 someLibLoad();
131             };
132         };
133 
134         thread2 = new Thread() {
135             public void run() {
136                 try {
137                     Class c = Class.forName("Target", true, loader);
138                     System.out.println(c);
139                 } catch (Exception e) {
140                     throw new RuntimeException(e);
141                 }
142             };
143         };
144 
145         thread1.setDaemon(true);
146         thread2.setDaemon(true);
147 
148         thread1.start();
149         thread2.start();
150 
151         thread1.join();
152         thread2.join();
153 
154         if (!loader.passed()) {
155             throw new RuntimeException("FAIL");
156         }
157     }
158 }
159