/
githubmirror
/
jdk22
Обзор
Документация
Войти
/
githubmirror
/
jdk22
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/java.base/share/classes/jdk/internal/reflect/AccessorUtils.java
109 строк
5 KB
Mandy Chung
8271820: Implementation of JEP 416: Reimplement Core Reflection with Method Handle
28 окт 2021, 21:32
28 окт 2021, 21:32
c6339cb
Код
Авторство
О чём код?
/* * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package jdk.internal.reflect; import java.lang.invoke.WrongMethodTypeException; import java.util.Set; /** * Utility methods used by DirectMethodHandleAccessor and DirectConstructorHandleAccessor */ public class AccessorUtils { /** * Determines if the given exception thrown by MethodHandle::invokeExact * is caused by an illegal argument passed to Method::invoke or * Constructor::newInstance. This method inspects the stack trace of * the exception to detect if it is thrown by the method handle core * implementation or the implementation of the reflected method or constructor. * * MethodHandle::invoke throws ClassCastException if the receiver object * is not an instance of the declaring class of the method if the method * is an instance method, or if a parameter value cannot be converted * to the corresponding formal parameter type. It throws * NullPointerException if the receiver object is null if the method * is an instance method, or if unboxing operation of a parameter fails * because the parameter value is null. It throws WrongMethodTypeException * if the method type mismatches. * * @param accessorType the accessor class that does the method handle invocation * @param e ClassCastException, NullPointerException or WrongMethodTypeException */ static boolean isIllegalArgument(Class<?> accessorType, RuntimeException e) { assert(e instanceof ClassCastException || e instanceof NullPointerException || e instanceof WrongMethodTypeException); StackTraceElement[] stackTrace = e.getStackTrace(); if (stackTrace.length == 0) { return false; // would this happen? } int i = 0; StackTraceElement frame = stackTrace[0]; // Class::cast and Objects::requiresNonNull may be thrown by the implementation // of the reflected method/constructor. Skip them and continue. if ((frame.getClassName().equals("java.lang.Class") && frame.getMethodName().equals("cast")) || (frame.getClassName().equals("java.util.Objects") && frame.getMethodName().equals("requiresNonNull"))) { i++; } for (; i < stackTrace.length; i++) { frame = stackTrace[i]; String cname = frame.getClassName(); // it's illegal argument if this exception is thrown from accessorType if (cname.equals(accessorType.getName())) { return true; } // if this exception is thrown from an unnamed module or not from java.base // then i.e. not from method handle core implementation if (frame.getModuleName() == null || !frame.getModuleName().equals("java.base")) { return false; } int index = cname.lastIndexOf("."); String pn = index > 0 ? cname.substring(0, index) : ""; // exception thrown from java.base but not from core reflection/method handle internals if (!IMPL_PACKAGES.contains(pn)) { return false; } // If Constructor::newInstance is invoked by Method::invoke or vice versa, // so the exception is thrown from the implementation body of the reflected // method or constructor if ((accessorType == DirectMethodHandleAccessor.class && cname.startsWith(DirectConstructorHandleAccessor.class.getName())) || (accessorType == DirectConstructorHandleAccessor.class && cname.startsWith(DirectMethodHandleAccessor.class.getName()))) { // thrown from another reflection accessor impl class return false; } } return false; } private static final Set<String> IMPL_PACKAGES = Set.of( "java.lang.reflect", "java.lang.invoke", "jdk.internal.reflect", "sun.invoke.util" ); }