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 8163162 35 * @summary Checks that LazyLoggers are returned for System.Logger instances 36 * created by modules in the platform class loader. 37 * @modules java.base/java.lang:open 38 * @build systempkg.log.SystemLoggerAccessor SystemLoggerInPlatformLoader 39 * @run main/othervm SystemLoggerInPlatformLoader 40 * @author danielfuchs 41 */ 42 public class SystemLoggerInPlatformLoader { 43 44 static final class PlatformClassLoaderChild extends ClassLoader { 45 private PlatformClassLoaderChild() { 46 super(ClassLoader.getPlatformClassLoader()); 47 } 48 public Class<?> definePlatformClass(String name) throws IOException { 49 String testClasses = System.getProperty("test.classes", "./build/classes"); 50 String fname = name.replace('.', '/').concat(".class"); 51 try (InputStream is = new FileInputStream(new File(testClasses, fname))) { 52 byte[] b = is.readAllBytes(); 53 ClassLoader parent = getParent(); 54 try { 55 Method m = ClassLoader.class.getDeclaredMethod("defineClass", 56 String.class, byte[].class, int.class, int.class); 57 m.setAccessible(true); 58 return (Class<?>)m.invoke(parent, name, b, 0, b.length); 59 } catch (NoSuchMethodException 60 | IllegalAccessException 61 | InvocationTargetException ex) { 62 throw new IOException(ex); 63 } 64 } 65 } 66 static final PlatformClassLoaderChild INSTANCE = new PlatformClassLoaderChild(); 67 static Class<?> loadLoggerAccessor() throws IOException { 68 return INSTANCE.definePlatformClass("systempkg.log.SystemLoggerAccessor"); 69 } 70 } 71 72 static final Class<?> LOGGER_ACCESSOR_CLASS; 73 static { 74 try { 75 LOGGER_ACCESSOR_CLASS = PlatformClassLoaderChild.loadLoggerAccessor(); 76 ClassLoader platformCL = ClassLoader.getPlatformClassLoader(); 77 if (LOGGER_ACCESSOR_CLASS.getClassLoader() != platformCL) { 78 throw new ExceptionInInitializerError( 79 "Could not load accessor class in platform class loader: " 80 + LOGGER_ACCESSOR_CLASS.getClassLoader()); 81 } 82 } catch (IOException ex) { 83 throw new ExceptionInInitializerError(ex); 84 } 85 } 86 87 // Returns a system logger created on behalf of a class loaded by the 88 // Platform ClassLoader 89 static System.Logger getSystemLogger(String name) { 90 try { 91 return (System.Logger)LOGGER_ACCESSOR_CLASS.getMethod( 92 "getSystemLogger", String.class).invoke(null, name); 93 } catch (NoSuchMethodException 94 | IllegalAccessException 95 | InvocationTargetException ex) { 96 throw new RuntimeException("Failed to invoke LoggerAccessor.getJULLogger", ex); 97 } 98 } 99 100 public static void main(String[] args) { 101 System.Logger splogger = getSystemLogger("bar"); // for a platform class 102 System.Logger slogger = System.getLogger("bar"); // for an application class 103 if (slogger == splogger) { 104 throw new RuntimeException("Same loggers"); 105 } 106 Class sploggerType = splogger.getClass(); 107 System.out.println("splogger: " + sploggerType); 108 if (!sploggerType.getSimpleName().equals("JdkLazyLogger")) { 109 throw new RuntimeException(sploggerType.getSimpleName() 110 + ": unexpected class for splogger" 111 + " (expected a lazy logger for a platform class)"); 112 } 113 Class sloggerType = slogger.getClass(); 114 System.out.println("slogger: " + sloggerType); 115 if (sloggerType.equals(sploggerType)) { 116 throw new RuntimeException(sloggerType 117 + ": unexpected class for slogger" 118 + " (a lazy logger was not expected" 119 + " for a non platform class)"); 120 } 121 } 122 }