58 // constructor. If it does not find it, it delegates to the super class loader. 59 // 60 // A // interface 61 // | 62 // B // Compiled to the current working directory so that it is found by our 63 // // special class loader. B uses D, so that loading B triggers loading D. 64 // 65 // C // An abstract class. 66 // | 67 // D // Class with two different implementations D1 and D2. D2 is 68 // // compiled to the current working directory so that it is found by our 69 // // special class loader. 70 // 71 // First, the bootstrap loader will load D1. It already has loaded interface A. 72 // Then, the second class loader PreemptingClassLoader will load B. Recursive, 73 // it tries to load interface A. As it does not find it (there is no A.impl2), 74 // it asks the super classloader for A. 75 // Then it loads the D2 variant of D from the current working directory and it's 76 // superclass C. This fails as D1 is already loaded with the same superclass. 77 78 static String expectedErrorMessage = 79 "loader constraint violation: loader \"<unnamed>\" (instance of PreemptingClassLoader, " + 80 "child of \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) wants to load " + 81 "class test.D_ambgs. A different class with the same name was previously loaded " + 82 "by \"app\" (instance of jdk.internal.loader.ClassLoaders$AppClassLoader)."; 83 84 public static void test_access() throws Exception { 85 try { 86 // Make a Class 'D_ambgs' under the default loader. 87 // This uses the implementation from the .java file. 88 C c_1 = new D_ambgs(); 89 90 // Some classes under a new Loader, loader2, including, indirectly, 91 // another version of 'D_ambgs' 92 String[] classNames = {"test.B", "test.D_ambgs"}; 93 94 ClassLoader loader2 = new PreemptingClassLoader(null, classNames, false); 95 Class class2 = loader2.loadClass("test.B"); 96 A iface = (A)class2.newInstance(); 97 98 // Call D1.make() loaded by bootstrap loader with B loaded by Loader2. 99 D_ambgs[] x2 = c_1.make(iface); 100 101 throw new RuntimeException("Expected LinkageError was not thrown."); 102 } catch (LinkageError jle) { 103 String errorMsg = jle.getMessage(); 104 if (!errorMsg.equals(expectedErrorMessage)) { 105 System.out.println("Expected: " + expectedErrorMessage + "\n" + 106 "but got: " + errorMsg); 107 throw new RuntimeException("Wrong error message of LinkageError."); 108 } else { 109 System.out.println("Passed with message: " + errorMsg); 110 } 111 } 112 } 113 114 public static void main(String[] args) throws Exception { 115 test_access(); 116 } 117 } 118 | 58 // constructor. If it does not find it, it delegates to the super class loader. 59 // 60 // A // interface 61 // | 62 // B // Compiled to the current working directory so that it is found by our 63 // // special class loader. B uses D, so that loading B triggers loading D. 64 // 65 // C // An abstract class. 66 // | 67 // D // Class with two different implementations D1 and D2. D2 is 68 // // compiled to the current working directory so that it is found by our 69 // // special class loader. 70 // 71 // First, the bootstrap loader will load D1. It already has loaded interface A. 72 // Then, the second class loader PreemptingClassLoader will load B. Recursive, 73 // it tries to load interface A. As it does not find it (there is no A.impl2), 74 // it asks the super classloader for A. 75 // Then it loads the D2 variant of D from the current working directory and it's 76 // superclass C. This fails as D1 is already loaded with the same superclass. 77 78 // Break the expectedErrorMessage into 2 pieces since the loader name will include 79 // its identity hash and can not be compared against. 80 static String expectedErrorMessage_part1 = "loader constraint violation: loader PreemptingClassLoader @"; 81 static String expectedErrorMessage_part2 = " (instance of PreemptingClassLoader, " + 82 "child of 'app' jdk.internal.loader.ClassLoaders$AppClassLoader) wants to load " + 83 "class test.D_ambgs. A different class with the same name was previously loaded " + 84 "by 'app' (instance of jdk.internal.loader.ClassLoaders$AppClassLoader)."; 85 86 public static void test_access() throws Exception { 87 try { 88 // Make a Class 'D_ambgs' under the default loader. 89 // This uses the implementation from the .java file. 90 C c_1 = new D_ambgs(); 91 92 // Some classes under a new Loader, loader2, including, indirectly, 93 // another version of 'D_ambgs' 94 String[] classNames = {"test.B", "test.D_ambgs"}; 95 96 ClassLoader loader2 = new PreemptingClassLoader(null, classNames, false); 97 Class class2 = loader2.loadClass("test.B"); 98 A iface = (A)class2.newInstance(); 99 100 // Call D1.make() loaded by bootstrap loader with B loaded by Loader2. 101 D_ambgs[] x2 = c_1.make(iface); 102 103 throw new RuntimeException("Expected LinkageError was not thrown."); 104 } catch (LinkageError jle) { 105 String errorMsg = jle.getMessage(); 106 if (!errorMsg.contains(expectedErrorMessage_part1) || 107 !errorMsg.contains(expectedErrorMessage_part2)) { 108 System.out.println("Expected: " + expectedErrorMessage_part1 + "<id>" + expectedErrorMessage_part2 + "\n" + 109 "but got: " + errorMsg); 110 throw new RuntimeException("Wrong error message of LinkageError."); 111 } else { 112 System.out.println("Passed with message: " + errorMsg); 113 } 114 } 115 } 116 117 public static void main(String[] args) throws Exception { 118 test_access(); 119 } 120 } 121 |