< prev index next >

src/java.base/share/classes/java/lang/Class.java

Print this page
rev 58768 : 8238358: Implementation of JEP 371: Hidden Classes
Reviewed-by: alanb, cjplummer, coleenp, dholmes, dlong, forax, jlahoda, psandoz, plevart, vromero
Contributed-by: mandy.chung@oracle.com, lois.foltan@oracle.com, david.holmes@oracle.com, harold.seigel@oracle.com, serguei.spitsyn@oracle.com, alex.buckley@oracle.com, jamsheed.c.m@oracle.com, jan.lahoda@oracle.com, amy.lu@oracle.com
rev 58769 : [mq]: type-descriptor-name

*** 161,174 **** * hidden classes; all kinds of interface, including annotation types, * may be hidden interfaces. * * The {@linkplain #getName() name of a hidden class or interface} is * not a <a href="ClassLoader.html#binary-name">binary name</a>, ! * which means that a hidden class or interface cannot be ! * referenced by the constant pools of other classes and interfaces, ! * and cannot be discovered by {@link #forName Class::forName} or ! * {@link ClassLoader#loadClass(String, boolean) ClassLoader::loadClass}. * * A hidden class or interface is never an array class, but may be * the element type of an array. In all other respects, the fact that * a class or interface is hidden has no bearing on the characteristics * exposed by the methods of class {@code Class}. --- 161,182 ---- * hidden classes; all kinds of interface, including annotation types, * may be hidden interfaces. * * The {@linkplain #getName() name of a hidden class or interface} is * not a <a href="ClassLoader.html#binary-name">binary name</a>, ! * which means the following: ! * <ul> ! * <li>A hidden class or interface cannot be referenced by the constant pools ! * of other classes and interfaces. ! * <li>A hidden class or interface cannot be described in ! * {@linkplain java.lang.constant.ConstantDesc <em>nominal form</em>} by ! * {@link #describeConstable() Class::describeConstable}, ! * {@link ClassDesc#of(String) ClassDesc::of}, or ! * {@link ClassDesc#ofDescriptor(String) ClassDesc::ofDescriptor}. ! * <li>A hidden class or interface cannot be discovered by {@link #forName Class::forName} ! * or {@link ClassLoader#loadClass(String, boolean) ClassLoader::loadClass}. ! * </ul> * * A hidden class or interface is never an array class, but may be * the element type of an array. In all other respects, the fact that * a class or interface is hidden has no bearing on the characteristics * exposed by the methods of class {@code Class}.
*** 1063,1076 **** * @jls 6.7 Fully Qualified Names */ public String getPackageName() { String pn = this.packageName; if (pn == null) { ! Class<?> c = this; ! while (c.isArray()) { ! c = c.getComponentType(); ! } if (c.isPrimitive()) { pn = "java.lang"; } else { String cn = c.getName(); int dot = cn.lastIndexOf('.'); --- 1071,1081 ---- * @jls 6.7 Fully Qualified Names */ public String getPackageName() { String pn = this.packageName; if (pn == null) { ! Class<?> c = isArray() ? elementType() : this; if (c.isPrimitive()) { pn = "java.lang"; } else { String cn = c.getName(); int dot = cn.lastIndexOf('.');
*** 1224,1233 **** --- 1229,1252 ---- } } private final Class<?> componentType; + /* + * Returns the {@code Class} representing the element type of an array class. + * If this class does not represent an array class, then this method returns + * {@code null}. + */ + private Class<?> elementType() { + if (!isArray()) return null; + + Class<?> c = this; + while (c.isArray()) { + c = c.getComponentType(); + } + return c; + } /** * Returns the Java language modifiers for this class or interface, encoded * in an integer. The modifiers consist of the Java Virtual Machine's * constants for {@code public}, {@code protected},
*** 3021,3034 **** * Add a package name prefix if the name is not absolute Remove leading "/" * if name is absolute */ private String resolveName(String name) { if (!name.startsWith("/")) { ! Class<?> c = this; ! while (c.isArray()) { ! c = c.getComponentType(); ! } String baseName = c.getPackageName(); if (baseName != null && !baseName.isEmpty()) { name = baseName.replace('.', '/') + "/" + name; } } else { --- 3040,3050 ---- * Add a package name prefix if the name is not absolute Remove leading "/" * if name is absolute */ private String resolveName(String name) { if (!name.startsWith("/")) { ! Class<?> c = isArray() ? elementType() : this; String baseName = c.getPackageName(); if (baseName != null && !baseName.isEmpty()) { name = baseName.replace('.', '/') + "/" + name; } } else {
*** 4239,4266 **** } return members; } /** ! * Returns the type descriptor string for this class. ! * <p> ! * Note that this is not a strict inverse of {@link #forName}; * distinct classes which share a common name but have different class loaders * will have identical descriptor strings. * ! * @return the type descriptor representation * @jvms 4.3.2 Field Descriptors * @since 12 */ @Override public String descriptorString() { if (isPrimitive()) return Wrapper.forPrimitiveType(this).basicTypeString(); ! else if (isArray()) { return "[" + componentType.descriptorString(); ! } ! else { return "L" + getName().replace('.', '/') + ";"; } } /** --- 4255,4331 ---- } return members; } /** ! * Returns the descriptor string of the entity (class, interface, array class, ! * primitive type, or {@code void}) represented by this {@code Class} object. ! * ! * <p> If this {@code Class} object represents a class or interface, ! * not an array class, then: ! * <ul> ! * <li> If the class or interface is not {@linkplain Class#isHidden() hidden}, ! * then the result is a field descriptor (JVMS {@jvms 4.3.2}) ! * for the class or interface. Calling ! * {@link ClassDesc#ofDescriptor(String) ClassDesc::ofDescriptor} ! * with the result descriptor string produces a {@link ClassDesc ClassDesc} ! * describing this class or interface. ! * <li> If the class or interface is {@linkplain Class#isHidden() hidden}, ! * then the result is a string of the form: ! * <blockquote> ! * {@code "L" +} <em>N</em> {@code + "." + <suffix> + ";"} ! * </blockquote> ! * where <em>N</em> is the <a href="ClassLoader.html#binary-name">binary name</a> ! * encoded in internal form indicated by the {@code class} file passed to ! * {@link MethodHandles.Lookup#defineHiddenClass(byte[], boolean, MethodHandles.Lookup.ClassOption...) ! * Lookup::defineHiddenClass}, and {@code <suffix>} is an unqualified name. ! * A hidden class or interface has no {@linkplain ClassDesc nominal descriptor}. ! * The result string is not a type descriptor. ! * </ul> ! * ! * <p> If this {@code Class} object represents an array class, then ! * the result is a string consisting of one or more '{@code [}' characters ! * representing the depth of the array nesting, followed by the ! * descriptor string of the element type. ! * <ul> ! * <li> If the element type is not a {@linkplain Class#isHidden() hidden} class ! * or interface, then this array class can be described nominally. ! * Calling {@link ClassDesc#ofDescriptor(String) ClassDesc::ofDescriptor} ! * with the result descriptor string produces a {@link ClassDesc ClassDesc} ! * describing this array class. ! * <li> If the element type is a {@linkplain Class#isHidden() hidden} class or ! * interface, then this array class cannot be described nominally. ! * The result string is not a type descriptor. ! * </ul> ! * ! * <p> If this {@code Class} object represents a primitive type or ! * {@code void}, then the result is a field descriptor string which ! * is a one-letter code corresponding to a primitive type or {@code void} ! * ({@code "B", "C", "D", "F", "I", "J", "S", "Z", "V"}) (JVMS {@jvms 4.3.2}). ! * ! * @apiNote ! * This is not a strict inverse of {@link #forName}; * distinct classes which share a common name but have different class loaders * will have identical descriptor strings. * ! * @return the descriptor string for this {@code Class} object * @jvms 4.3.2 Field Descriptors * @since 12 */ @Override public String descriptorString() { if (isPrimitive()) return Wrapper.forPrimitiveType(this).basicTypeString(); ! ! if (isArray()) { return "[" + componentType.descriptorString(); ! } else if (isHidden()) { ! String name = getName(); ! int index = name.indexOf('/'); ! return "L" + name.substring(0, index).replace('.', '/') ! + "." + name.substring(index+1) + ";"; ! } else { return "L" + getName().replace('.', '/') + ";"; } } /**
*** 4299,4309 **** * or an empty {@link Optional} if one cannot be constructed. * @since 12 */ @Override public Optional<ClassDesc> describeConstable() { ! return Optional.of(ClassDesc.ofDescriptor(descriptorString())); } /** * Returns {@code true} if and only if the underlying class is a hidden class. * --- 4364,4376 ---- * or an empty {@link Optional} if one cannot be constructed. * @since 12 */ @Override public Optional<ClassDesc> describeConstable() { ! Class<?> c = isArray() ? elementType() : this; ! return c.isHidden() ? Optional.empty() ! : Optional.of(ClassDesc.ofDescriptor(descriptorString())); } /** * Returns {@code true} if and only if the underlying class is a hidden class. *
< prev index next >