8304139: Add <init> and <clinit> method constants to ConstantDescs

Reviewed-by: mchung
This commit is contained in:
Chen Liang 2023-03-21 16:16:08 +00:00 committed by Mandy Chung
parent d6f20e2fbf
commit 019fcd819c
7 changed files with 56 additions and 21 deletions

View File

@ -27,6 +27,7 @@ package java.lang;
import java.lang.annotation.Annotation;
import java.lang.constant.ClassDesc;
import java.lang.constant.ConstantDescs;
import java.lang.invoke.TypeDescriptor;
import java.lang.invoke.MethodHandles;
import java.lang.module.ModuleReader;
@ -1524,9 +1525,9 @@ public final class Class<T> implements java.io.Serializable,
return enclosingClass == null || name == null || descriptor == null;
}
boolean isConstructor() { return !isPartial() && "<init>".equals(name); }
boolean isConstructor() { return !isPartial() && ConstantDescs.INIT_NAME.equals(name); }
boolean isMethod() { return !isPartial() && !isConstructor() && !"<clinit>".equals(name); }
boolean isMethod() { return !isPartial() && !isConstructor() && !ConstantDescs.CLASS_INIT_NAME.equals(name); }
Class<?> getEnclosingClass() { return enclosingClass; }
@ -2040,8 +2041,8 @@ public final class Class<T> implements java.io.Serializable,
* has length 0. (Note that a {@code Class} object which represents a class
* always has public methods, inherited from {@code Object}.)
*
* <p> The returned array never contains methods with names "{@code <init>}"
* or "{@code <clinit>}".
* <p> The returned array never contains methods with names {@value
* ConstantDescs#INIT_NAME} or {@value ConstantDescs#CLASS_INIT_NAME}.
*
* <p> The elements in the returned array are not sorted and are not in any
* particular order.
@ -2234,8 +2235,8 @@ public final class Class<T> implements java.io.Serializable,
* this interface or any of its superinterfaces, then this method does not
* find any method.
*
* <p> This method does not find any method with name "{@code <init>}" or
* "{@code <clinit>}".
* <p> This method does not find any method with name {@value
* ConstantDescs#INIT_NAME} or {@value ConstantDescs#CLASS_INIT_NAME}.
*
* <p> Generally, the method to be reflected is determined by the 4 step
* algorithm that follows.
@ -2293,7 +2294,8 @@ public final class Class<T> implements java.io.Serializable,
* @return the {@code Method} object that matches the specified
* {@code name} and {@code parameterTypes}
* @throws NoSuchMethodException if a matching method is not found
* or if the name is "&lt;init&gt;"or "&lt;clinit&gt;".
* or if the name is {@value ConstantDescs#INIT_NAME} or
* {@value ConstantDescs#CLASS_INIT_NAME}.
* @throws NullPointerException if {@code name} is {@code null}
* @throws SecurityException
* If a security manager, <i>s</i>, is present and
@ -2549,8 +2551,9 @@ public final class Class<T> implements java.io.Serializable,
* object for each such method.
*
* <p> If this {@code Class} object represents a class or interface that
* has a class initialization method {@code <clinit>}, then the returned
* array does <em>not</em> have a corresponding {@code Method} object.
* has a class initialization method {@value ConstantDescs#CLASS_INIT_NAME},
* then the returned array does <em>not</em> have a corresponding {@code
* Method} object.
*
* <p> If this {@code Class} object represents a class or interface with no
* declared methods, then the returned array has length 0.
@ -2721,7 +2724,8 @@ public final class Class<T> implements java.io.Serializable,
* parameter types is declared in a class, and one of these methods has a
* return type that is more specific than any of the others, that method is
* returned; otherwise one of the methods is chosen arbitrarily. If the
* name is "&lt;init&gt;"or "&lt;clinit&gt;" a {@code NoSuchMethodException}
* name is {@value ConstantDescs#INIT_NAME} or {@value
* ConstantDescs#CLASS_INIT_NAME} a {@code NoSuchMethodException}
* is raised.
*
* <p> If this {@code Class} object represents an array type, then this

View File

@ -30,6 +30,7 @@ import jdk.internal.misc.VM;
import jdk.internal.module.ModuleHashes;
import jdk.internal.module.ModuleReferenceImpl;
import java.lang.constant.ConstantDescs;
import java.lang.module.ModuleReference;
import java.lang.module.ResolvedModule;
import java.util.HashSet;
@ -262,9 +263,9 @@ public final class StackTraceElement implements java.io.Serializable {
* Returns the name of the method containing the execution point
* represented by this stack trace element. If the execution point is
* contained in an instance or class initializer, this method will return
* the appropriate <i>special method name</i>, {@code <init>} or
* {@code <clinit>}, as per Section {@jvms 3.9} of <cite>The Java Virtual
* Machine Specification</cite>.
* the appropriate <i>special method name</i>, {@value ConstantDescs#INIT_NAME}
* or {@value ConstantDescs#CLASS_INIT_NAME}, as per Section {@jvms 3.9}
* of <cite>The Java Virtual Machine Specification</cite>.
*
* @return the name of the method containing the execution point
* represented by this stack trace element.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2023, 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
@ -299,6 +299,33 @@ public final class ConstantDescs {
= DynamicConstantDesc.ofNamed(BSM_GET_STATIC_FINAL,
"FALSE", CD_Boolean, CD_Boolean);
/**
* The special name of instance initialization methods, {@value}. An instance
* initialization method has this special name and is {@code void}.
*
* @jvms 2.9.1 Instance Initialization Methods
* @since 21
*/
public static final String INIT_NAME = "<init>";
/**
* The special name of class initialization methods, {@value}. A class
* initialization method has this special name, {@link java.lang.reflect.AccessFlag#STATIC
* ACC_STATIC} flag set, is {@link #MTD_void void} and takes no arguments.
*
* @jvms 2.9.2 Class Initialization Methods
* @since 21
*/
public static final String CLASS_INIT_NAME = "<clinit>";
/**
* Nominal descriptor representing the method descriptor {@code ()V},
* taking no argument and returning {@code void}.
*
* @since 21
*/
public static final MethodTypeDesc MTD_void = MethodTypeDesc.of(CD_void);
static final DirectMethodHandleDesc MHD_METHODHANDLE_ASTYPE
= MethodHandleDesc.ofMethod(Kind.VIRTUAL, CD_MethodHandle, "asType",
MethodTypeDesc.of(CD_MethodHandle, CD_MethodType));

View File

@ -39,7 +39,7 @@ class ConstantUtils {
static final Constable[] EMPTY_CONSTABLE = new Constable[0];
static final int MAX_ARRAY_TYPE_DESC_DIMENSIONS = 255;
private static final Set<String> pointyNames = Set.of("<init>", "<clinit>");
private static final Set<String> pointyNames = Set.of(ConstantDescs.INIT_NAME, ConstantDescs.CLASS_INIT_NAME);
/**
* Validates the correctness of a binary class name. In particular checks for the presence of

View File

@ -231,7 +231,7 @@ public sealed interface DirectMethodHandleDesc
/**
* Returns the name of the method or field described by this nominal descriptor.
* For constructors, returns the reserved name {@code "<init>"}.
* For constructors, returns the reserved name {@value ConstantDescs#INIT_NAME}.
*
* @return the name of the method or field
*/

View File

@ -160,7 +160,8 @@ public interface MethodHandleInfo {
/**
* Returns the name of the cracked method handle's underlying member.
* This is {@code "<init>"} if the underlying member was a constructor,
* This is {@value java.lang.constant.ConstantDescs#INIT_NAME}
* if the underlying member was a constructor,
* else it is a simple method name or field name.
* @return the simple name of the underlying member
*/

View File

@ -712,7 +712,8 @@ public class MethodHandles {
* (See the Java Virtual Machine Specification, section {@jvms 4.10.1.9}.)
* <p>
* The JVM represents constructors and static initializer blocks as internal methods
* with special names ({@code "<init>"} and {@code "<clinit>"}).
* with special names ({@value ConstantDescs#INIT_NAME} and {@value
* ConstantDescs#CLASS_INIT_NAME}).
* The internal syntax of invocation instructions allows them to refer to such internal
* methods as if they were normal methods, but the JVM bytecode verifier rejects them.
* A lookup of such an internal method will produce a {@code NoSuchMethodException}.
@ -2768,7 +2769,7 @@ assertEquals("[x, y, z]", pb.command().toString());
if (refc.isArray()) {
throw new NoSuchMethodException("no constructor for array class: " + refc.getName());
}
String name = "<init>";
String name = ConstantDescs.INIT_NAME;
MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
return getDirectConstructor(refc, ctor);
}
@ -2964,7 +2965,8 @@ assertEquals("[x, y, z]", pb.command().toString());
* {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
* the method's variable arity modifier bit ({@code 0x0080}) is set.
* <p style="font-size:smaller;">
* <em>(Note: JVM internal methods named {@code "<init>"} are not visible to this API,
* <em>(Note: JVM internal methods named {@value ConstantDescs#INIT_NAME}
* are not visible to this API,
* even though the {@code invokespecial} instruction can refer to them
* in special circumstances. Use {@link #findConstructor findConstructor}
* to access instance initialization methods in a safe manner.)</em>
@ -4002,7 +4004,7 @@ return mh1;
!refc.isInterface() &&
refc != lookupClass().getSuperclass() &&
refc.isAssignableFrom(lookupClass())) {
assert(!method.getName().equals("<init>")); // not this code path
assert(!method.getName().equals(ConstantDescs.INIT_NAME)); // not this code path
// Per JVMS 6.5, desc. of invokespecial instruction:
// If the method is in a superclass of the LC,