1 /* 2 * Copyright (c) 2016, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 import java.io.File; 27 import java.io.FileInputStream; 28 import java.io.IOException; 29 import java.io.InputStream; 30 import java.lang.reflect.InvocationTargetException; 31 import java.lang.reflect.Method; 32 33 /* 34 * @test 35 * @bug 8163162 36 * @summary Checks that LazyLoggers are returned for System.Logger instances 37 * created by modules in the platform class loader. 38 * @modules java.base/java.lang:open 39 * @build systempkg.log.SystemLoggerAccessor SystemLoggerInPlatformLoader 40 * @run main/othervm SystemLoggerInPlatformLoader 41 * @author danielfuchs 42 */ 43 public class SystemLoggerInPlatformLoader { 44 45 static final class PlatformClassLoaderChild extends ClassLoader { 46 private PlatformClassLoaderChild() { 47 super(ClassLoader.getPlatformClassLoader()); 48 } 49 public Class<?> definePlatformClass(String name) throws IOException { 50 String testClasses = System.getProperty("test.classes", "./build/classes"); 51 String fname = name.replace('.', '/').concat(".class"); 52 try (InputStream is = new FileInputStream(new File(testClasses, fname))) { 53 byte[] b = is.readAllBytes(); 54 ClassLoader parent = getParent(); 55 try { 56 Method m = ClassLoader.class.getDeclaredMethod("defineClass", 57 String.class, byte[].class, int.class, int.class); 58 m.setAccessible(true); 59 return (Class<?>)m.invoke(parent, name, b, 0, b.length); 60 } catch (NoSuchMethodException 61 | IllegalAccessException 62 | InvocationTargetException ex) { 63 throw new IOException(ex); 64 } 65 } 66 } 67 static final PlatformClassLoaderChild INSTANCE = new PlatformClassLoaderChild(); 68 static Class<?> loadLoggerAccessor() throws IOException { 69 return INSTANCE.definePlatformClass("systempkg.log.SystemLoggerAccessor"); 70 } 71 } 72 73 static final Class<?> LOGGER_ACCESSOR_CLASS; 74 static { 75 try { 76 LOGGER_ACCESSOR_CLASS = PlatformClassLoaderChild.loadLoggerAccessor(); 77 ClassLoader platformCL = ClassLoader.getPlatformClassLoader(); 78 if (LOGGER_ACCESSOR_CLASS.getClassLoader() != platformCL) { 79 throw new ExceptionInInitializerError( 80 "Could not load accessor class in platform class loader: " 81 + LOGGER_ACCESSOR_CLASS.getClassLoader()); 82 } 83 } catch (IOException ex) { 84 throw new ExceptionInInitializerError(ex); 85 } 86 } 87 88 // Returns a system logger created on behalf of a class loaded by the 89 // Platform ClassLoader 90 static System.Logger getSystemLogger(String name) { 91 try { 92 return (System.Logger)LOGGER_ACCESSOR_CLASS.getMethod( 93 "getSystemLogger", String.class).invoke(null, name); 94 } catch (NoSuchMethodException 95 | IllegalAccessException 96 | InvocationTargetException ex) { 97 throw new RuntimeException("Failed to invoke LoggerAccessor.getJULLogger", ex); 98 } 99 } 100 101 public static void main(String[] args) { 102 System.Logger platformLogger = getSystemLogger("bar"); // for a platform class 103 System.Logger appLogger = System.getLogger("bar"); // for an application class 104 if (appLogger == platformLogger) { 105 throw new RuntimeException("Same loggers"); 106 } 107 Class<?> platformLoggerType = platformLogger.getClass(); 108 System.out.println("platformLogger: " + platformLoggerType); 109 boolean simpleConsoleOnly = !ModuleLayer.boot().findModule("java.logging").isPresent(); 110 if (simpleConsoleOnly) { 111 /* Happens if the test is called with custom JDK without java.logging module 112 or in case usage commandline option --limit-modules java.base */ 113 if (!platformLoggerType.getSimpleName().equals("SimpleConsoleLogger")) { 114 throw new RuntimeException(platformLoggerType.getSimpleName() 115 + ": unexpected class for platform logger" 116 + " (expected a simple console logger class)"); 117 } 118 } else { 119 if (!platformLoggerType.getSimpleName().equals("JdkLazyLogger")) { 120 throw new RuntimeException(platformLoggerType.getSimpleName() 121 + ": unexpected class for platform logger" 122 + " (expected a lazy logger for a platform class)"); 123 } 124 Class<?> appLoggerType = appLogger.getClass(); 125 System.out.println("appLogger: " + appLoggerType); 126 if (appLoggerType.equals(platformLoggerType)) { 127 throw new RuntimeException(appLoggerType 128 + ": unexpected class for application logger" 129 + " (a lazy logger was not expected" 130 + " for a non platform class)"); 131 } 132 } 133 } 134 }