1 /* 2 * Copyright (c) 2020, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package jdk.internal.loader; 25 26 import java.lang.reflect.Constructor; 27 import java.net.MalformedURLException; 28 import java.net.URL; 29 import java.net.URLClassLoader; 30 import java.nio.file.Paths; 31 32 public class NativeLibrariesTest implements Runnable { 33 public static final String LIB_NAME = "nativeLibrariesTest"; 34 // increments when JNI_OnLoad and JNI_OnUnload is invoked. 35 // This is only for JNI native library 36 private static int loadedCount = 0; 37 private static int unloadedCount = 0; 38 /* 39 * Called by JNI_OnLoad when the native library is unloaded 40 */ 41 static void nativeLibraryLoaded() { 42 loadedCount++; 43 } 44 45 /* 46 * Called by JNI_OnUnload when the native library is unloaded 47 */ 48 static void nativeLibraryUnloaded() { 49 unloadedCount++; 50 } 51 52 private final NativeLibraries nativeLibraries; 53 public NativeLibrariesTest() { 54 this.nativeLibraries = NativeLibraries.rawNativeLibraries(NativeLibraries.class, true); 55 } 56 57 /* 58 * Invoke by p.Test to load the same native library from different class loader 59 */ 60 public void run() { 61 load(true); // expect loading of native library succeed 62 } 63 64 public void runTest() throws Exception { 65 NativeLibrary nl1 = nativeLibraries.loadLibrary(LIB_NAME); 66 NativeLibrary nl2 = nativeLibraries.loadLibrary(LIB_NAME); 67 assertTrue(nl1 != null && nl2 != null, "fail to load library"); 68 assertTrue(nl1 == nl2, nl1 + " != " + nl2); 69 assertTrue(loadedCount == 0, "Native library loaded. Expected: JNI_OnUnload not invoked"); 70 assertTrue(unloadedCount == 0, "native library never unloaded"); 71 72 // load successfully even from another loader 73 loadWithCustomLoader(); 74 75 // unload the native library 76 nativeLibraries.unload(nl1); 77 assertTrue(unloadedCount == 0, "Native library unloaded. Expected: JNI_OnUnload not invoked"); 78 79 // reload the native library and expect new NativeLibrary instance 80 NativeLibrary nl3 = nativeLibraries.loadLibrary(LIB_NAME); 81 assertTrue(nl1 != nl3, nl1 + " == " + nl3); 82 assertTrue(loadedCount == 0, "Native library loaded. Expected: JNI_OnUnload not invoked"); 83 84 // load successfully even from another loader 85 loadWithCustomLoader(); 86 } 87 88 public void unload() { 89 NativeLibrary nl = nativeLibraries.loadLibrary(LIB_NAME); 90 // unload the native library 91 nativeLibraries.unload(nl); 92 assertTrue(unloadedCount == 0, "Native library unloaded. Expected: JNI_OnUnload not invoked"); 93 } 94 95 public void load(boolean succeed) { 96 NativeLibrary nl = nativeLibraries.loadLibrary(LIB_NAME); 97 if (succeed) { 98 assertTrue(nl != null, "fail to load library"); 99 } else { 100 assertTrue(nl == null, "load library should fail"); 101 } 102 } 103 104 /* 105 * Loads p.Test class with a new class loader and invokes the run() method. 106 * p.Test::run invokes NativeLibrariesTest::run 107 */ 108 private void loadWithCustomLoader() throws Exception { 109 TestLoader loader = new TestLoader(); 110 Class<?> c = Class.forName("p.Test", true, loader); 111 Constructor<?> ctr = c.getConstructor(Runnable.class); 112 Runnable r = (Runnable) ctr.newInstance(this); 113 r.run(); 114 } 115 116 static class TestLoader extends URLClassLoader { 117 static URL[] toURLs() { 118 try { 119 return new URL[] { Paths.get("classes").toUri().toURL() }; 120 } catch (MalformedURLException e) { 121 throw new Error(e); 122 } 123 } 124 125 TestLoader() { 126 super("testloader", toURLs(), ClassLoader.getSystemClassLoader()); 127 } 128 } 129 130 static void assertTrue(boolean value, String msg) { 131 if (!value) { 132 throw new AssertionError(msg); 133 } 134 } 135 }