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 java.lang.invoke; 25 26 import jdk.internal.loader.BuiltinClassLoader; 27 import jdk.internal.misc.VM; 28 29 final class LambdaProxyClassArchive { 30 private static final boolean dumpArchive; 31 private static final boolean sharingEnabled; 32 33 static { 34 dumpArchive = VM.isCDSDumpingEnabled(); 35 sharingEnabled = VM.isCDSSharingEnabled(); 36 } 37 38 /** 39 * Check if CDS dynamic dump is enabled. 40 */ 41 static boolean isDumpArchive() { 42 return dumpArchive; 43 } 44 45 /** 46 * Check if CDS sharing is enabled. 47 */ 48 static boolean isSharingEnabled() { 49 return sharingEnabled; 50 } 51 52 /** 53 * Check if the class is loaded by a built-in class loader. 54 */ 55 static boolean loadedByBuiltinLoader(Class<?> cls) { 56 ClassLoader cl = cls.getClassLoader(); 57 return (cl == null || (cl instanceof BuiltinClassLoader)) ? true : false; 58 } 59 60 private static native void addToArchive(Class<?> caller, 61 String invokedName, 62 MethodType invokedType, 63 MethodType samMethodType, 64 MemberName implMethod, 65 MethodType instantiatedMethodType, 66 Class<?> lambdaProxyClass); 67 68 private static native Class<?> findFromArchive(Class<?> caller, 69 String invokedName, 70 MethodType invokedType, 71 MethodType samMethodType, 72 MemberName implMethod, 73 MethodType instantiatedMethodType, 74 boolean initialize); 75 76 /** 77 * Registers the lambdaProxyClass into CDS archive. 78 * The VM will store the lambdaProxyClass into a hash table 79 * using the first six argumennts as the key. 80 * 81 * CDS only archives lambda proxy class if it's not serializable 82 * and no marker interfaces and no additional bridges, and if it is 83 * loaded by a built-in class loader. 84 */ 85 static boolean register(Class<?> caller, 86 String invokedName, 87 MethodType invokedType, 88 MethodType samMethodType, 89 MethodHandle implMethod, 90 MethodType instantiatedMethodType, 91 boolean isSerializable, 92 Class<?>[] markerInterfaces, 93 MethodType[] additionalBridges, 94 Class<?> lambdaProxyClass) { 95 if (!isDumpArchive()) 96 throw new IllegalStateException("should only register lambda proxy class at dump time"); 97 98 if (loadedByBuiltinLoader(caller) && 99 !isSerializable && markerInterfaces.length == 0 && additionalBridges.length == 0) { 100 addToArchive(caller, invokedName, invokedType, samMethodType, 101 implMethod.internalMemberName(), instantiatedMethodType, 102 lambdaProxyClass); 103 return true; 104 } 105 return false; 106 } 107 108 /** 109 * Lookup a lambda proxy class from the CDS archive using the first 110 * six arguments as the key. 111 * 112 * CDS only archives lambda proxy class if it's not serializable 113 * and no marker interfaces and no additional bridges, and if it is 114 * loaded by a built-in class loader. 115 */ 116 static Class<?> find(Class<?> caller, 117 String invokedName, 118 MethodType invokedType, 119 MethodType samMethodType, 120 MethodHandle implMethod, 121 MethodType instantiatedMethodType, 122 boolean isSerializable, 123 Class<?>[] markerInterfaces, 124 MethodType[] additionalBridges, 125 boolean initialize) { 126 if (isDumpArchive()) 127 throw new IllegalStateException("cannot load class from CDS archive at dump time"); 128 129 if (!loadedByBuiltinLoader(caller) || 130 !isSharingEnabled() || isSerializable || markerInterfaces.length > 0 || additionalBridges.length > 0) 131 return null; 132 133 return findFromArchive(caller, invokedName, invokedType, samMethodType, 134 implMethod.internalMemberName(), instantiatedMethodType, initialize); 135 } 136 }