1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2018 SAP SE. 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  * @summary Test exception messages of LinkageError.
  28  * @compile LE2_D_ambgs.jasm
  29  * @run shell myMove.sh LE2_D_ambgs.class LE2_D_ambgs.impl2
  30  * @compile LinkageErrorTest.java LE1.java LE2_B.java
  31  * @run shell myMove.sh LE2_B.class LE2_B.impl2
  32  * @run main/othervm -Xbootclasspath/a:. LinkageErrorTest
  33  */
  34 
  35 import java.io.ByteArrayOutputStream;
  36 import java.io.InputStream;
  37 
  38 import java.io.*;
  39 import java.nio.file.Files;
  40 import java.nio.file.Path;
  41 import java.nio.file.Paths;
  42 
  43 public class LinkageErrorTest {
  44 
  45     static private class LE1_Loader extends ClassLoader {
  46         public LE1_Loader() {
  47             super();
  48         }
  49 
  50         public LE1_Loader(String name) {
  51             super(name, ClassLoader.getSystemClassLoader());
  52         }
  53 
  54         public Class<?> myDefineClass(String name, byte[] b, int off, int len) throws ClassFormatError {
  55             return defineClass(name, b, off, len, null);
  56         }
  57     }
  58 
  59     private static byte[] le1_getBytecodes(String myName) throws Exception {
  60         InputStream is = LinkageErrorTest.class.getResourceAsStream(myName + ".class");
  61         if (is == null) {
  62             System.out.println("is is null. File " + myName + ".class not found.");
  63         }
  64         ByteArrayOutputStream baos = new ByteArrayOutputStream();
  65         byte[] buf = new byte[4096];
  66         int len;
  67         while ((len = is.read(buf)) != -1) { baos.write(buf, 0, len); }
  68         buf = baos.toByteArray();
  69         System.out.println("sizeof(" + myName + ".class) == " + buf.length);
  70         return buf;
  71     }
  72 
  73     private static String expectedErrorMessageDuplicate1 =
  74         "loader LinkageErrorTest$LE1_Loader (parent: \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) " +
  75         "attempted duplicate class definition for test.LE1.";
  76 
  77     // Load the same class twice.
  78     // This test is derived from runtime/Metaspace/DefineClass.java.
  79     public static void test1_duplicate1() throws Exception {
  80         String myName = "test.LE1";
  81         byte[] buf = le1_getBytecodes(myName.replace('.', '/'));
  82         LE1_Loader cl = new LE1_Loader();
  83 
  84         try {
  85             @SuppressWarnings("unchecked")
  86             Class<LinkageErrorTest> dc = (Class<LinkageErrorTest>) cl.myDefineClass(myName, buf, 0, buf.length);
  87             System.out.println(dc);
  88             // Should throw exception in SystemDictionary::check_constraints(), check for duplicates.
  89             dc = (Class<LinkageErrorTest>) cl.myDefineClass(myName, buf, 0, buf.length);
  90             throw new RuntimeException("Expected LinkageError was not thrown.");
  91         } catch (NoClassDefFoundError exc) {
  92             throw new RuntimeException("Unexpected NoClassDefFoundError: " + exc);
  93         } catch (LinkageError jle) {
  94             // Second definition should fail. Check error message.
  95             String errorMsg = jle.getMessage();
  96             if (!errorMsg.equals(expectedErrorMessageDuplicate1)) {
  97                 System.out.println("Expected: " + expectedErrorMessageDuplicate1 + "\n" +
  98                                    "but got:  " + errorMsg);
  99                 throw new RuntimeException("Wrong error message of LinkageError.");
 100             } else {
 101                 System.out.println("Passed with message: " + errorMsg);
 102             }
 103         }
 104     }
 105 
 106     private static String expectedErrorMessageDuplicate2 =
 107         "loader \"LoaderForTestLE1_2\" (instance of LinkageErrorTest$LE1_Loader, " +
 108         "parent: \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) " +
 109         "attempted duplicate class definition for test.LE1.";
 110 
 111     // Load the same class twice. Use classloader with explicit name.
 112     // This test is derived from runtime/Metaspace/DefineClass.java.
 113     public static void test1_duplicate2() throws Exception {
 114         String myName = "test.LE1";
 115         byte[] buf = le1_getBytecodes(myName.replace('.', '/'));
 116         LE1_Loader cl = new LE1_Loader("LoaderForTestLE1_2");
 117 
 118         try {
 119             @SuppressWarnings("unchecked")
 120             Class<LinkageErrorTest> dc = (Class<LinkageErrorTest>) cl.myDefineClass(myName, buf, 0, buf.length);
 121             System.out.println(dc);
 122             // Should throw exception in SystemDictionary::check_constraints(), check for duplicates.
 123             dc = (Class<LinkageErrorTest>) cl.myDefineClass(myName, buf, 0, buf.length);
 124             throw new RuntimeException("Expected LinkageError was not thrown.");
 125         } catch (NoClassDefFoundError exc) {
 126             throw new RuntimeException("Unexpected NoClassDefFoundError: " + exc);
 127         } catch (LinkageError jle) {
 128             // Second definition should fail. Check error message.
 129             String errorMsg = jle.getMessage();
 130             if (!errorMsg.equals(expectedErrorMessageDuplicate2)) {
 131                 System.out.println("Expected: " + expectedErrorMessageDuplicate2 + "\n" +
 132                                    "but got:  " + errorMsg);
 133                 throw new RuntimeException("Wrong error message of LinkageError.");
 134             } else {
 135                 System.out.println("Passed with message: " + errorMsg);
 136             }
 137         }
 138     }
 139 
 140     //  Force LinkageError.
 141     //
 142     //  Derived from test runtime/6626217.
 143     //
 144     //  Uses the specialized class loader LE2_Loader.
 145     //  LE2_Loader first looks for a file with ending ".impl2" to load. If
 146     //  it does not find it, it delegates to the super class loader.
 147     //
 148     //  A    // interface
 149     //  |
 150     //  B    // Compiled to B.impl2 so that it is found by our special class loader.
 151     //       // B uses D, so that loading B triggers loading D.
 152     //
 153     //  C    // An abstract class.
 154     //  |
 155     //  D    // Class with two different implementations D1 and D2. D2 is
 156     //       // compiled to D.impl2 so that it is found by our special class loader.
 157     //
 158     // First, the bootstrap loader will load D1. It already has loaded interface A.
 159     // Then, the second class loader LE2_Loader will load B. Recursive, it tries to
 160     // load interface A. As it does not find it (there is no A.impl2), it asks the
 161     // bootstrap classloader for A.
 162     // Then it loads the D2 variant of D from D.impl2 and it's superclass C. This
 163     // fails as D1 is already loaded with the same superclass.
 164 
 165     static String expectedErrorMessage2 =
 166         "loader constraint violation: loader LE2_Loader " +
 167         "(parent: \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) wants to load " +
 168         "class LE2_D_ambgs. A different class with the same name was previously loaded " +
 169         "by \"app\" (instance of jdk.internal.loader.ClassLoaders$AppClassLoader, " +
 170         "parent: \"platform\" jdk.internal.loader.ClassLoaders$PlatformClassLoader).";
 171 
 172     public static void test2_access() throws Exception {
 173         try {
 174             // Make a Class 'LE2_D_ambgs' under the default loader.
 175             // This uses the implementation from the .java file.
 176             LE2_C c_1 = new LE2_D_ambgs();
 177 
 178             // Some classes under a new Loader, loader2, including, indirectly,
 179             // another version of 'LE2_D_ambgs'
 180             ClassLoader loader2 = new LE2_Loader();
 181             Class       class2  = loader2.loadClass("LE2_B");
 182             LE2_A       iface   = (LE2_A)class2.newInstance();
 183 
 184             // Call D1.make() loaded by bootstrap loader with B loaded by Loader2.
 185             LE2_D_ambgs[] x2 = c_1.make(iface);
 186 
 187             throw new RuntimeException("Expected LinkageError was not thrown.");
 188         } catch (LinkageError jle) {
 189             String errorMsg = jle.getMessage();
 190             if (!errorMsg.equals(expectedErrorMessage2)) {
 191                 System.out.println("Expected: " + expectedErrorMessage2 + "\n" +
 192                                    "but got:  " + errorMsg);
 193                 throw new RuntimeException("Wrong error message of LinkageError.");
 194             } else {
 195                 System.out.println("Passed with message: " + errorMsg);
 196             }
 197         }
 198     }
 199 
 200     public static void main(String[] args) throws Exception {
 201         test1_duplicate1();
 202         test1_duplicate2();
 203         test2_access();
 204     }
 205 }
 206 
 207