Skip to content

Commit

Permalink
Merge pull request eclipse-openj9#18555 from JasonFengJ9/jdk22access
Browse files Browse the repository at this point in the history
JDK22+ adds JavaLangAccess.findMethod(isPublic, methodName, parameters)
  • Loading branch information
pshipton committed Dec 4, 2023
2 parents 244201c + 83d3267 commit 834b623
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 13 deletions.
6 changes: 6 additions & 0 deletions jcl/src/java.base/share/classes/java/lang/Access.java
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,12 @@ public boolean bytesCompatible(String string, Charset charset) {
public void copyToSegmentRaw(String string, MemorySegment segment, long offset) {
string.copyToSegmentRaw(segment, offset);
}

// No @Override to avoid breaking valhalla builds which is behind latest OpenJDK head stream update.
public Method findMethod(Class<?> clazz, boolean isPublic, String methodName, Class<?>... parameterTypes) {
return clazz.findMethod(isPublic, methodName, parameterTypes);
}

/*[ENDIF] JAVA_SPEC_VERSION >= 22 */

/*[IF INLINE-TYPES]*/
Expand Down
85 changes: 72 additions & 13 deletions jcl/src/java.base/share/classes/java/lang/Class.java
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,18 @@ private static final class AnnotationCache {
private static boolean reflectCacheDebug;
private static boolean reflectCacheAppOnly = true;

/*
* The target method types to be searched by getMethodHelper().
*/
enum SearchMethodType {
// all method types, public or not
ALL,
// public method only
PUBLIC,
// not public method
NOTPUBLIC,
}

/*
* This {@code ClassReflectNullPlaceHolder} class is created to indicate the cached class value is
* initialized to null rather than the default value null ;e.g. {@code cachedDeclaringClass}
Expand Down Expand Up @@ -1700,11 +1712,22 @@ private Method throwExceptionOrReturnNull(boolean throwException, String name, C
return null;
}
}

/**
* A convenient method for getMethodHelper() with SearchMethodType.ALL.
*/
Method getMethodHelper(
boolean throwException, boolean forDeclaredMethod, List<Method> methodList, String name, Class<?>... parameterTypes)
throws NoSuchMethodException {
return getMethodHelper(throwException, forDeclaredMethod, methodList, SearchMethodType.ALL, name, parameterTypes);
}

/**
* Helper method for
* public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
* public Method getMethod(String name, Class<?>... parameterTypes)
* List<Method> getDeclaredPublicMethods(String name, Class<?>... parameterTypes)
* Method findMethod(boolean isPublic, String methodName, Class<?>... parameterTypes)
* without going thorough security checking
*
* @param throwException boolean
Expand All @@ -1713,35 +1736,50 @@ private Method throwExceptionOrReturnNull(boolean throwException, String name, C
* @param forDeclaredMethod boolean
* true - for getDeclaredMethod(String name, Class<?>... parameterTypes)
* & getDeclaredPublicMethods(String name, Class<?>... parameterTypes);
* false - for getMethod(String name, Class<?>... parameterTypes);
* false - for getMethod(String name, Class<?>... parameterTypes)
* & findMethod(boolean isPublic, String methodName, Class<?>... parameterTypes);
* @param name String the name of the method
* @param parameterTypes Class<?>[] the types of the arguments
* @param methodList List<Method> a list to store the methods described by the arguments
* for getDeclaredPublicMethods()
* or null for getDeclaredMethod() & getMethod()
* or null for getDeclaredMethod(), getMethod() & findMethod()
* @param methodScope SearchMethodType the method type to be searched
* SearchMethodType.PUBLIC/NOTPUBLIC for findMethod()
* or SearchMethodType.ALL for others
* @return Method the method described by the arguments.
* @throws NoSuchMethodException if the method could not be found.
*/
@CallerSensitive
Method getMethodHelper(
boolean throwException, boolean forDeclaredMethod, List<Method> methodList, String name, Class<?>... parameterTypes)
boolean throwException, boolean forDeclaredMethod, List<Method> methodList, SearchMethodType searchMethodType, String name, Class<?>... parameterTypes)
throws NoSuchMethodException {
Method result;
Method bestCandidate;
String strSig;
boolean candidateFromInterface = false;

boolean searchAllMethods = searchMethodType == SearchMethodType.ALL;
boolean searchPublicMethodOnly = searchMethodType == SearchMethodType.PUBLIC;

/*[PR CMVC 114820, CMVC 115873, CMVC 116166] add reflection cache */
if (parameterTypes == null) {
parameterTypes = EmptyParameters;
}
if (methodList == null) {
// getDeclaredPublicMethods() has to go through all methods anyway
Method cachedMethod = lookupCachedMethod(name, parameterTypes);
if ((cachedMethod != null)
&& ((forDeclaredMethod && (cachedMethod.getDeclaringClass() == this))
|| (!forDeclaredMethod && Modifier.isPublic(cachedMethod.getModifiers())))) {
return cachedMethod;
if (cachedMethod != null) {
if (searchAllMethods && forDeclaredMethod && (cachedMethod.getDeclaringClass() == this)) {
return cachedMethod;
} else {
boolean isPublic = Modifier.isPublic(cachedMethod.getModifiers());
if (searchAllMethods) {
if (!forDeclaredMethod && isPublic) {
return cachedMethod;
}
} else if (searchPublicMethodOnly == isPublic) {
return cachedMethod;
}
}
}
}

Expand Down Expand Up @@ -1782,7 +1820,7 @@ Method getMethodHelper(
}
}
}

if (result == null) {
return throwExceptionOrReturnNull(throwException, name, parameterTypes);
}
Expand All @@ -1807,7 +1845,8 @@ Method getMethodHelper(
}
}
}
if ((methodList != null) && ((result.getModifiers() & Modifier.PUBLIC) != 0)) {
boolean publicMethodInitialResult = Modifier.isPublic(result.getModifiers());
if ((methodList != null) && publicMethodInitialResult) {
methodList.add(result);
}

Expand All @@ -1824,18 +1863,24 @@ Method getMethodHelper(
* Otherwise, the result method is chosen arbitrarily from specific methods.
*/
bestCandidate = result;
boolean initialResultShouldBeReplaced = !searchAllMethods && (publicMethodInitialResult != searchPublicMethodOnly);
if (!candidateFromInterface) {
Class<?> declaringClass = forDeclaredMethod ? this : result.getDeclaringClass();
while (true) {
result = declaringClass.getDeclaredMethodImpl(name, parameterTypes, strSig, result);
if (result == null) {
break;
}
boolean publicMethod = ((result.getModifiers() & Modifier.PUBLIC) != 0);
boolean publicMethod = Modifier.isPublic(result.getModifiers());
if ((methodList != null) && publicMethod) {
methodList.add(result);
}
if (forDeclaredMethod || publicMethod) {
boolean searchIsPublic = !searchAllMethods && (searchPublicMethodOnly == publicMethod);
if (searchIsPublic && initialResultShouldBeReplaced) {
// Current result is the method type to be found but the initial result wasn't.
bestCandidate = result;
initialResultShouldBeReplaced = false;
} else if (forDeclaredMethod || publicMethod || searchIsPublic) {
// bestCandidate and result have same declaringClass.
Class<?> candidateRetType = bestCandidate.getReturnType();
Class<?> resultRetType = result.getReturnType();
Expand All @@ -1845,7 +1890,12 @@ Method getMethodHelper(
}
}
}
return cacheMethod(bestCandidate);
if (!searchAllMethods && initialResultShouldBeReplaced) {
// The initial result doesn't match the searching method type.
return null;
} else {
return cacheMethod(bestCandidate);
}
}

/**
Expand Down Expand Up @@ -5819,5 +5869,14 @@ public static Class<?> forPrimitiveName(String typeName) {
default -> null;
};
}

Method findMethod(boolean isPublic, String methodName, Class<?>... parameterTypes) {
try {
return getMethodHelper(true, false, null, isPublic ? SearchMethodType.PUBLIC : SearchMethodType.NOTPUBLIC,
methodName, parameterTypes);
} catch (NoSuchMethodException nsme) {
return null;
}
}
/*[ENDIF] JAVA_SPEC_VERSION >= 22 */
}

0 comments on commit 834b623

Please sign in to comment.