1 /* 2 * Copyright (c) 2024, 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 package java.lang.reflect.code.type.impl; 27 28 import java.lang.reflect.code.op.CoreOp; 29 import java.lang.reflect.code.type.MethodRef; 30 import java.lang.invoke.MethodHandle; 31 import java.lang.invoke.MethodHandleInfo; 32 import java.lang.invoke.MethodHandles; 33 import java.lang.invoke.MethodType; 34 import java.lang.reflect.Method; 35 import java.lang.reflect.code.type.FunctionType; 36 import java.lang.reflect.code.type.JavaType; 37 import java.lang.reflect.code.TypeElement; 38 import java.util.Optional; 39 40 import static java.util.stream.Collectors.joining; 41 42 public final class MethodRefImpl implements MethodRef { 43 final TypeElement refType; 44 final String name; 45 final FunctionType type; 46 47 public MethodRefImpl(TypeElement refType, String name, FunctionType type) { 48 this.refType = refType; 49 this.name = name; 50 this.type = type; 51 } 52 53 @Override 54 public TypeElement refType() { 55 return refType; 56 } 57 58 @Override 59 public String name() { 60 return name; 61 } 62 63 @Override 64 public FunctionType type() { 65 return type; 66 } 67 68 @Override 69 public Method resolveToMember(MethodHandles.Lookup l) throws ReflectiveOperationException { 70 // @@@ Constructor 71 MethodHandleInfo methodHandleInfo = l.revealDirect(resolveToHandle(l)); 72 return methodHandleInfo.reflectAs(Method.class, l); 73 } 74 75 @Override 76 public MethodHandle resolveToHandle(MethodHandles.Lookup l) throws ReflectiveOperationException { 77 // @@@ kind 78 Class<?> refC = resolve(l, refType); 79 80 MethodType mt = MethodRef.toNominalDescriptor(type).resolveConstantDesc(l); 81 82 MethodHandle mh = null; 83 ReflectiveOperationException c = null; 84 85 try { 86 mh = l.findStatic(refC, name, mt); 87 } catch (NoSuchMethodException | IllegalAccessException e) { 88 c = e; 89 } 90 91 if (c != null) { 92 c = null; 93 try { 94 mh = l.findVirtual(refC, name, mt); 95 } catch (NoSuchMethodException | IllegalAccessException e) { 96 c = e; 97 } 98 } 99 100 if (c != null) { 101 throw c; 102 } 103 104 assert mh != null; 105 return mh; 106 } 107 108 static Class<?> resolve(MethodHandles.Lookup l, TypeElement t) throws ReflectiveOperationException { 109 if (t instanceof JavaType jt) { 110 return (Class<?>)jt.erasure().resolve(l); 111 } else { 112 // @@@ 113 throw new ReflectiveOperationException(); 114 } 115 } 116 117 // Copied code in jdk.compiler module throws UOE 118 @Override 119 public Optional<CoreOp.FuncOp> codeModel(MethodHandles.Lookup l) throws ReflectiveOperationException { 120 /*__throw new UnsupportedOperationException();__*/ return resolveToMember(l).getCodeModel(); 121 } 122 123 @Override 124 public String toString() { 125 return refType + "::" + name + 126 type.parameterTypes().stream().map(TypeElement::toString) 127 .collect(joining(", ", "(", ")")) + type.returnType(); 128 } 129 130 @Override 131 public boolean equals(Object o) { 132 if (this == o) return true; 133 if (o == null || getClass() != o.getClass()) return false; 134 135 MethodRefImpl that = (MethodRefImpl) o; 136 137 if (!refType.equals(that.refType)) return false; 138 if (!name.equals(that.name)) return false; 139 return type.equals(that.type); 140 } 141 142 @Override 143 public int hashCode() { 144 int result = refType.hashCode(); 145 result = 31 * result + name.hashCode(); 146 result = 31 * result + type.hashCode(); 147 return result; 148 } 149 }