1 /* 2 * Copyright (c) 2015, 2018, 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 /* 25 * @test 26 * @bug 8141615 27 * @summary Tests new public methods at ConstantPool 28 * @modules java.base/jdk.internal.misc 29 * java.base/jdk.internal.reflect 30 * @library /test/lib 31 * @compile ConstantPoolTestDummy.jasm 32 * @run main jdk.internal.reflect.constantPool.ConstantPoolTest 33 */ 34 35 package jdk.internal.reflect.constantPool; 36 37 import java.util.TreeMap; 38 import java.util.Map; 39 import jdk.internal.misc.SharedSecrets; 40 import jdk.test.lib.Asserts; 41 import jdk.internal.reflect.ConstantPool; 42 43 public class ConstantPoolTest { 44 45 private static final Class<?> TEST_CLASS = ConstantPoolTestDummy.class; 46 private static final ConstantPool CP = SharedSecrets.getJavaLangAccess() 47 .getConstantPool(TEST_CLASS); 48 49 public static void main(String[] s) throws Throwable { 50 TEST_CLASS.newInstance(); 51 for (TestCase testCase : TestCase.values()) { 52 testCase.test(); 53 } 54 } 55 56 public static enum TestCase { 57 GET_TAG_AT { 58 { 59 referenceMap.put(1, ConstantPool.Tag.METHODREF); 60 referenceMap.put(2, ConstantPool.Tag.CLASS); 61 referenceMap.put(4, ConstantPool.Tag.UTF8); 62 referenceMap.put(10, ConstantPool.Tag.NAMEANDTYPE); 63 referenceMap.put(13, ConstantPool.Tag.LONG); 64 referenceMap.put(15, ConstantPool.Tag.INTEGER); 65 referenceMap.put(16, ConstantPool.Tag.INTERFACEMETHODREF); 66 referenceMap.put(21, ConstantPool.Tag.DOUBLE); 67 referenceMap.put(23, ConstantPool.Tag.STRING); 68 referenceMap.put(25, ConstantPool.Tag.INVOKEDYNAMIC); 69 referenceMap.put(29, ConstantPool.Tag.METHODHANDLE); 70 referenceMap.put(30, ConstantPool.Tag.METHODTYPE); 71 referenceMap.put(48, ConstantPool.Tag.FIELDREF); 72 referenceMap.put(52, ConstantPool.Tag.FLOAT); 73 referenceMap.put(53, ConstantPool.Tag.DYNAMIC); 74 } 75 @Override 76 void testIndex(int cpi, Object reference) { 77 ConstantPool.Tag tagToVerify = CP.getTagAt(cpi); 78 ConstantPool.Tag tagToRefer = (ConstantPool.Tag) reference; 79 String msg = String.format("Method getTagAt works not as expected" 80 + "at CP entry #%d: got CP tag %s, but should be %s", 81 cpi, tagToVerify.name(), tagToRefer.name()); 82 Asserts.assertEquals(tagToVerify, tagToRefer, msg); 83 } 84 }, 85 GET_CONSTANT_AT { 86 { 87 referenceMap.put(3, Object.class); 88 referenceMap.put(13, (long)6); 89 referenceMap.put(15, (int)1); 90 referenceMap.put(17, Runnable.class); 91 referenceMap.put(21, (double)1.45); 92 referenceMap.put(23, "Hello"); 93 referenceMap.put(31, "[a method handle]"); 94 referenceMap.put(52, (float)1.34); 95 //referenceMap.put(53, "[a dynamic constant]"); 96 } 97 @Override 98 void testIndex(int cpi, Object reference) { 99 Object entryToVerify = CP.getConstantAt(cpi); 100 Object entryToRefer = reference; 101 if (cpi == 31 && entryToVerify instanceof java.lang.invoke.MethodHandle) { 102 // const #31 = MethodHandle 5:#34; // REF_invokeVirtual:java/lang/Object.toString:"()Ljava/lang/String;" 103 entryToVerify = entryToRefer; // good enough 104 } 105 String msg = String.format("Method getConstantAt works not" 106 + " as expected at CP entry #%d:" 107 + " got %s, but should be %s", 108 cpi, entryToVerify, entryToRefer); 109 Asserts.assertEquals(entryToVerify, entryToRefer, msg); 110 } 111 }, 112 GET_CONSTANTDESC_AT { 113 { 114 referenceMap.put(3, Object.class); 115 referenceMap.put(13, (long)6); 116 referenceMap.put(15, (int)1); 117 referenceMap.put(17, Runnable.class); 118 referenceMap.put(21, (double)1.45); 119 referenceMap.put(23, "Hello"); 120 referenceMap.put(31, "[a method handle]"); 121 referenceMap.put(52, (float)1.34); 122 referenceMap.put(53, "[a dynamic constant]"); 123 } 124 @Override 125 void testIndex(int cpi, Object reference) { 126 Object entryToVerify = CP.getConstantDescAt(cpi); 127 Object entryToRefer = ((java.lang.constant.Constable<?>)reference).describeConstable().orElse(null); 128 if (cpi == 31 && entryToVerify instanceof java.lang.constant.MethodHandleDesc) { 129 String str = entryToVerify.toString(); 130 // MethodHandleDesc[VIRTUAL/Object::toString()String] 131 if (str.contains("toString") && 132 str.contains("Object") && 133 str.contains("()") && 134 (str.contains("virtual") || str.contains("Virtual") || str.contains("VIRTUAL"))) 135 // close enough 136 entryToVerify = entryToRefer; 137 } 138 if (cpi == 53 && entryToVerify instanceof java.lang.constant.DynamicConstantDesc) { 139 // DynamicConstantDesc[LambdaMetafactory::metafactory( 140 // toString/MethodTypeDesc[(Object)void], 141 // MethodHandleDesc[VIRTUAL/Object::toString()String], 142 // MethodTypeDesc[(Object)void] 143 // )Object], 144 String str = entryToVerify.toString(); 145 if (str.contains("toString") && 146 str.contains("metafactory") && 147 str.contains("(Object)void")) 148 // close enough 149 entryToVerify = entryToRefer; 150 } 151 String msg = String.format("Method getConstantDescAt works not" 152 + " as expected at CP entry #%d:" 153 + " got %s, but should be %s", 154 cpi, entryToVerify, entryToRefer); 155 Asserts.assertEquals(entryToVerify, entryToRefer, msg); 156 } 157 }, 158 GET_CLASS_AT { 159 { 160 referenceMap.put(3, Object.class); 161 referenceMap.put(17, Runnable.class); 162 } 163 @Override 164 void testIndex(int cpi, Object reference) { 165 Object entryToVerify = CP.getClassAt(cpi); 166 Object entryToRefer = reference; 167 String msg = String.format("Method getClassAt works not" 168 + " as expected at CP entry #%d:" 169 + " got %s, but should be %s", 170 cpi, entryToVerify, entryToRefer); 171 Asserts.assertEquals(entryToVerify, entryToRefer, msg); 172 } 173 }, 174 GET_CLASS_REF_INDEX_AT { 175 { 176 referenceMap.put(1, 3); 177 referenceMap.put(16, 17); 178 referenceMap.put(32, 35); 179 referenceMap.put(34, 3); 180 referenceMap.put(48, 2); 181 } 182 @Override 183 void testIndex(int cpi, Object reference) { 184 int indexToVerify = CP.getClassRefIndexAt(cpi); 185 int indexToRefer = (int) reference; 186 String msg = String.format("Method getClassRefIndexAt works not" 187 + " as expected at CP entry #%d:" 188 + " got index %d, but should be %d", 189 cpi, indexToVerify, indexToRefer); 190 Asserts.assertEquals(indexToVerify, indexToRefer, msg); 191 } 192 }, 193 GET_NAME_AND_TYPE_REF_INDEX_AT { 194 { 195 referenceMap.put(1, 10); 196 referenceMap.put(16, 18); 197 referenceMap.put(25, 26); 198 referenceMap.put(32, 36); 199 referenceMap.put(34, 37); 200 referenceMap.put(48, 49); 201 } 202 @Override 203 void testIndex(int cpi, Object reference) { 204 int indexToRefer = (int) reference; 205 int indexToVerify = CP.getNameAndTypeRefIndexAt(cpi); 206 String msg = String.format("Method getNameAndTypeRefIndexAt works" 207 + " not as expected at CP entry #%d:" 208 + " got index %d, but should be %d", 209 cpi, indexToVerify, indexToRefer); 210 Asserts.assertEquals(indexToVerify, indexToRefer, msg); 211 } 212 }, 213 GET_NAME_AND_TYPE_REF_INFO_AT { 214 { 215 referenceMap.put(10, new String[]{"<init>", "()V"}); 216 referenceMap.put(18, new String[]{"run", "()V"}); 217 referenceMap.put(26, new String[]{"accept", "()Ljava/util/function/Consumer;"}); 218 referenceMap.put(36, new String[]{"metafactory", 219 "(Ljava/lang/invoke/MethodHandles$Lookup;" 220 + "Ljava/lang/String;Ljava/lang/invoke/MethodType;" 221 + "Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;" 222 + "Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"}); 223 referenceMap.put(37, new String[]{"toString", "()Ljava/lang/String;"}); 224 referenceMap.put(49, new String[]{"myField", "I"}); 225 } 226 @Override 227 void testIndex(int cpi, Object reference) { 228 String[] natInfo = CP.getNameAndTypeRefInfoAt(cpi); 229 String msg = String.format("Method getNameAndTypeRefInfoAt" 230 + " works not as expected at CP entry #%d:" 231 + " returned value should not be null", cpi); 232 Asserts.assertNotNull(natInfo, msg); 233 String[] castedReference = (String[]) reference; 234 int natInfoLength = natInfo.length; 235 msg = String.format("Method getNameAndTypeRefInfoAt" 236 + " works not as expected at CP entry #%d:" 237 + " length of the returned string array is %d, but should be 2", 238 cpi, natInfoLength); 239 Asserts.assertEquals(natInfoLength, 2, msg); 240 String[] nameOrType = new String[]{"name", "type"}; 241 for (int i = 0; i < 2; i++) { 242 String infoToVerify = natInfo[i]; 243 String infoToRefer = castedReference[i]; 244 msg = String.format("Method getNameAndTypeRefInfoAt" 245 + " works not as expected at CP entry #%d:" 246 + " got %s info %s, but should be %s", 247 cpi, nameOrType[i], infoToVerify, infoToRefer); 248 Asserts.assertEquals(infoToVerify, infoToRefer, msg); 249 } 250 } 251 }; 252 253 protected final Map<Integer, Object> referenceMap; 254 TestCase() { 255 // Use a TreeMap for deterministic test order. 256 this.referenceMap = new TreeMap<>(); 257 } 258 abstract void testIndex(int cpi, Object reference); 259 public void test() { 260 System.out.println(this); 261 referenceMap.forEach(this::testIndex); 262 } 263 } 264 }