This commit is contained in:
Jesper Wilhelmsson 2020-06-22 18:23:49 +02:00
commit 4862d0d542
80 changed files with 959 additions and 250 deletions
src
test

@ -231,6 +231,9 @@ static bool trust_final_non_static_fields(ciInstanceKlass* holder) {
// Trust final fields in all boxed classes
if (holder->is_box_klass())
return true;
// Trust final fields in records
if (holder->is_record())
return true;
// Trust final fields in String
if (holder->name() == ciSymbol::java_lang_String())
return true;

@ -64,6 +64,7 @@ ciInstanceKlass::ciInstanceKlass(Klass* k) :
_has_nonstatic_concrete_methods = ik->has_nonstatic_concrete_methods();
_is_unsafe_anonymous = ik->is_unsafe_anonymous();
_is_hidden = ik->is_hidden();
_is_record = ik->is_record();
_nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
_has_injected_fields = -1;
_implementor = NULL; // we will fill these lazily
@ -125,6 +126,7 @@ ciInstanceKlass::ciInstanceKlass(ciSymbol* name,
_has_injected_fields = -1;
_is_unsafe_anonymous = false;
_is_hidden = false;
_is_record = false;
_loader = loader;
_protection_domain = protection_domain;
_is_shared = false;

@ -57,6 +57,7 @@ private:
bool _has_nonstatic_concrete_methods;
bool _is_unsafe_anonymous;
bool _is_hidden;
bool _is_record;
ciFlags _flags;
jint _nonstatic_field_size;
@ -200,6 +201,10 @@ public:
return _is_hidden;
}
bool is_record() const {
return _is_record;
}
ciInstanceKlass* get_canonical_holder(int offset);
ciField* get_field_by_offset(int field_offset, bool is_static);
ciField* get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static);

@ -3141,6 +3141,7 @@ int java_lang_reflect_Field::_name_offset;
int java_lang_reflect_Field::_type_offset;
int java_lang_reflect_Field::_slot_offset;
int java_lang_reflect_Field::_modifiers_offset;
int java_lang_reflect_Field::_trusted_final_offset;
int java_lang_reflect_Field::_signature_offset;
int java_lang_reflect_Field::_annotations_offset;
@ -3150,6 +3151,7 @@ int java_lang_reflect_Field::_annotations_offset;
macro(_type_offset, k, vmSymbols::type_name(), class_signature, false); \
macro(_slot_offset, k, vmSymbols::slot_name(), int_signature, false); \
macro(_modifiers_offset, k, vmSymbols::modifiers_name(), int_signature, false); \
macro(_trusted_final_offset, k, vmSymbols::trusted_final_name(), bool_signature, false); \
macro(_signature_offset, k, vmSymbols::signature_name(), string_signature, false); \
macro(_annotations_offset, k, vmSymbols::annotations_name(), byte_array_signature, false);
@ -3214,6 +3216,10 @@ void java_lang_reflect_Field::set_modifiers(oop field, int value) {
field->int_field_put(_modifiers_offset, value);
}
void java_lang_reflect_Field::set_trusted_final(oop field) {
field->bool_field_put(_trusted_final_offset, true);
}
void java_lang_reflect_Field::set_signature(oop field, oop value) {
field->obj_field_put(_signature_offset, value);
}

@ -696,6 +696,7 @@ class java_lang_reflect_Field : public java_lang_reflect_AccessibleObject {
static int _type_offset;
static int _slot_offset;
static int _modifiers_offset;
static int _trusted_final_offset;
static int _signature_offset;
static int _annotations_offset;
@ -723,6 +724,8 @@ class java_lang_reflect_Field : public java_lang_reflect_AccessibleObject {
static int modifiers(oop field);
static void set_modifiers(oop field, int value);
static void set_trusted_final(oop field);
static void set_signature(oop constructor, oop value);
static void set_annotations(oop constructor, oop value);
static void set_parameter_annotations(oop method, oop value);
@ -1121,6 +1124,7 @@ class java_lang_invoke_MemberName: AllStatic {
MN_IS_FIELD = 0x00040000, // field
MN_IS_TYPE = 0x00080000, // nested type
MN_CALLER_SENSITIVE = 0x00100000, // @CallerSensitive annotation detected
MN_TRUSTED_FINAL = 0x00200000, // trusted final field
MN_REFERENCE_KIND_SHIFT = 24, // refKind
MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT,
// The SEARCH_* bits are not for MN.flags but for the matchFlags argument of MHN.getMembers:

@ -266,6 +266,7 @@
template(returnType_name, "returnType") \
template(signature_name, "signature") \
template(slot_name, "slot") \
template(trusted_final_name, "trustedFinal") \
\
/* Support for annotations (JDK 1.5 and above) */ \
\

@ -334,6 +334,13 @@ Node *ConvI2LNode::Ideal(PhaseGVN *phase, bool can_reshape) {
Node* z = in(1);
int op = z->Opcode();
if (op == Op_AddI || op == Op_SubI) {
if (!can_reshape) {
// Postpone this optimization to after parsing because with deep AddNode
// chains a large amount of dead ConvI2L nodes might be created that are
// not removed during parsing. As a result, we might hit the node limit.
phase->record_for_igvn(this);
return this_changed;
}
Node* x = z->in(1);
Node* y = z->in(2);
assert (x != z && y != z, "dead loop in ConvI2LNode::Ideal");

@ -126,6 +126,7 @@ enum {
IS_FIELD = java_lang_invoke_MemberName::MN_IS_FIELD,
IS_TYPE = java_lang_invoke_MemberName::MN_IS_TYPE,
CALLER_SENSITIVE = java_lang_invoke_MemberName::MN_CALLER_SENSITIVE,
TRUSTED_FINAL = java_lang_invoke_MemberName::MN_TRUSTED_FINAL,
REFERENCE_KIND_SHIFT = java_lang_invoke_MemberName::MN_REFERENCE_KIND_SHIFT,
REFERENCE_KIND_MASK = java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK,
SEARCH_SUPERCLASSES = java_lang_invoke_MemberName::MN_SEARCH_SUPERCLASSES,
@ -339,8 +340,10 @@ oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) {
}
oop MethodHandles::init_field_MemberName(Handle mname, fieldDescriptor& fd, bool is_setter) {
InstanceKlass* ik = fd.field_holder();
int flags = (jushort)( fd.access_flags().as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS );
flags |= IS_FIELD | ((fd.is_static() ? JVM_REF_getStatic : JVM_REF_getField) << REFERENCE_KIND_SHIFT);
if (fd.is_trusted_final()) flags |= TRUSTED_FINAL;
if (is_setter) flags += ((JVM_REF_putField - JVM_REF_getField) << REFERENCE_KIND_SHIFT);
int vmindex = fd.offset(); // determines the field uniquely when combined with static bit
@ -348,7 +351,7 @@ oop MethodHandles::init_field_MemberName(Handle mname, fieldDescriptor& fd, bool
java_lang_invoke_MemberName::set_flags (mname_oop, flags);
java_lang_invoke_MemberName::set_method (mname_oop, NULL);
java_lang_invoke_MemberName::set_vmindex(mname_oop, vmindex);
java_lang_invoke_MemberName::set_clazz (mname_oop, fd.field_holder()->java_mirror());
java_lang_invoke_MemberName::set_clazz (mname_oop, ik->java_mirror());
oop type = field_signature_type_or_null(fd.signature());
oop name = field_name_or_null(fd.name());
@ -1107,6 +1110,7 @@ void MethodHandles::trace_method_handle_interpreter_entry(MacroAssembler* _masm,
template(java_lang_invoke_MemberName,MN_IS_FIELD) \
template(java_lang_invoke_MemberName,MN_IS_TYPE) \
template(java_lang_invoke_MemberName,MN_CALLER_SENSITIVE) \
template(java_lang_invoke_MemberName,MN_TRUSTED_FINAL) \
template(java_lang_invoke_MemberName,MN_SEARCH_SUPERCLASSES) \
template(java_lang_invoke_MemberName,MN_SEARCH_INTERFACES) \
template(java_lang_invoke_MemberName,MN_REFERENCE_KIND_SHIFT) \

@ -58,6 +58,11 @@ Symbol* fieldDescriptor::generic_signature() const {
return NULL;
}
bool fieldDescriptor::is_trusted_final() const {
InstanceKlass* ik = field_holder();
return is_final() && (is_static() || ik->is_hidden() || ik->is_record());
}
AnnotationArray* fieldDescriptor::annotations() const {
InstanceKlass* ik = field_holder();
Array<AnnotationArray*>* md = ik->fields_annotations();

@ -102,6 +102,8 @@ class fieldDescriptor {
bool has_initialized_final_update() const { return access_flags().has_field_initialized_final_update(); }
bool has_generic_signature() const { return access_flags().field_has_generic_signature(); }
bool is_trusted_final() const;
inline void set_is_field_access_watched(const bool value);
inline void set_is_field_modification_watched(const bool value);
inline void set_has_initialized_final_update(const bool value);

@ -614,7 +614,7 @@ const size_t minimumSymbolTableSize = 1024;
product(bool, OmitStackTraceInFastThrow, true, \
"Omit backtraces for some 'hot' exceptions in optimized code") \
\
manageable(bool, ShowCodeDetailsInExceptionMessages, false, \
manageable(bool, ShowCodeDetailsInExceptionMessages, true, \
"Show exception messages from RuntimeExceptions that contain " \
"snippets of the failing code. Disable this to improve privacy.") \
\

@ -897,6 +897,9 @@ oop Reflection::new_field(fieldDescriptor* fd, TRAPS) {
java_lang_reflect_Field::set_slot(rh(), fd->index());
java_lang_reflect_Field::set_name(rh(), name());
java_lang_reflect_Field::set_type(rh(), type());
if (fd->is_trusted_final()) {
java_lang_reflect_Field::set_trusted_final(rh());
}
// Note the ACC_ANNOTATION bit, which is a per-class access flag, is never set here.
java_lang_reflect_Field::set_modifiers(rh(), fd->access_flags().as_int() & JVM_RECOGNIZED_FIELD_MODIFIERS);
java_lang_reflect_Field::set_override(rh(), false);

@ -112,7 +112,7 @@ public class PipedWriter extends Writer {
* Implements the {@code write} method of {@code Writer}.
*
* @param c the {@code char} to be written.
* @throw IOException if the pipe is
* @throws IOException if the pipe is
* <a href=PipedOutputStream.html#BROKEN> {@code broken}</a>,
* {@link #connect(java.io.PipedReader) unconnected}, closed
* or an I/O error occurs.

@ -121,7 +121,7 @@ public class SequenceInputStream extends InputStream {
* skipped over) from the current underlying input stream
* without blocking or {@code 0} if this input stream
* has been closed by invoking its {@link #close()} method
* @throw IOException if an I/O error occurs.
* @throws IOException if an I/O error occurs.
*
* @since 1.1
*/

@ -282,7 +282,7 @@ The resulting <code>run</code> method is:
}
}
</pre>
<hr size="3" noshade="noshade" />
<hr>
<h2>Can I combine the two techniques to produce a thread that may
be safely "stopped" or "suspended"?</h2>
Yes, it's reasonably straightforward. The one subtlety is that the
@ -324,6 +324,5 @@ If the <code>stop</code> method calls <code>Thread.interrupt</code>, as
described above, it needn't call <code>notify</code> as well, but it
still must be synchronized. This ensures that the target thread
won't miss an interrupt due to a race condition.
<p><!-- Body text ends here --></p>
</body>
</html>

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2020, 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
@ -480,7 +480,8 @@ final class MemberName implements Member, Cloneable {
IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
IS_FIELD = MN_IS_FIELD, // field
IS_TYPE = MN_IS_TYPE, // nested type
CALLER_SENSITIVE = MN_CALLER_SENSITIVE; // @CallerSensitive annotation detected
CALLER_SENSITIVE = MN_CALLER_SENSITIVE, // @CallerSensitive annotation detected
TRUSTED_FINAL = MN_TRUSTED_FINAL; // trusted final field
static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
@ -520,6 +521,8 @@ final class MemberName implements Member, Cloneable {
public boolean isCallerSensitive() {
return testAllFlags(CALLER_SENSITIVE);
}
/** Query whether this member is a trusted final field. */
public boolean isTrustedFinalField() { return testAllFlags(TRUSTED_FINAL|IS_FIELD); }
/** Utility method to query whether this member is accessible from a given lookup class. */
public boolean isAccessibleFrom(Class<?> lookupClass) {

@ -118,6 +118,7 @@ class MethodHandleNatives {
MN_IS_FIELD = 0x00040000, // field
MN_IS_TYPE = 0x00080000, // nested type
MN_CALLER_SENSITIVE = 0x00100000, // @CallerSensitive annotation detected
MN_TRUSTED_FINAL = 0x00200000, // trusted final field
MN_REFERENCE_KIND_SHIFT = 24, // refKind
MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT,
// The SEARCH_* bits are not for MN.flags but for the matchFlags argument of MHN.getMembers:

@ -3273,10 +3273,10 @@ return mh1;
private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAccessException {
MemberName field = new MemberName(f, isSetter);
if (isSetter && field.isFinal()) {
if (field.isStatic()) {
throw field.makeAccessException("static final field has no write access", this);
} else if (field.getDeclaringClass().isHidden()){
throw field.makeAccessException("final field in a hidden class has no write access", this);
if (field.isTrustedFinalField()) {
String msg = field.isStatic() ? "static final field has no write access"
: "final field has no write access";
throw field.makeAccessException(msg, this);
}
}
assert(isSetter
@ -3839,7 +3839,7 @@ return mh1;
refc = lookupClass();
}
return VarHandles.makeFieldHandle(getField, refc, getField.getFieldType(),
this.allowedModes == TRUSTED && !getField.getDeclaringClass().isHidden());
this.allowedModes == TRUSTED && !getField.isTrustedFinalField());
}
/** Check access and get the requested constructor. */
private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {

@ -177,10 +177,16 @@ public class AccessibleObject implements AnnotatedElement {
* to the caller's module. </p>
*
* <p> This method cannot be used to enable {@linkplain Field#set <em>write</em>}
* access to a final field declared in a {@linkplain Class#isHidden() hidden class},
* since such fields are not modifiable. The {@code accessible} flag when
* {@code true} suppresses Java language access control checks to only
* enable {@linkplain Field#get <em>read</em>} access to such fields.
* access to a <em>non-modifiable</em> final field. The following fields
* are non-modifiable:
* <ul>
* <li>static final fields declared in any class or interface</li>
* <li>final fields declared in a {@linkplain Class#isHidden() hidden class}</li>
* <li>final fields declared in a {@linkplain Class#isRecord() record}</li>
* </ul>
* <p> The {@code accessible} flag when {@code true} suppresses Java language access
* control checks to only enable {@linkplain Field#get <em>read</em>} access to
* these non-modifiable final fields.
*
* <p> If there is a security manager, its
* {@code checkPermission} method is first called with a

@ -72,6 +72,7 @@ class Field extends AccessibleObject implements Member {
private String name;
private Class<?> type;
private int modifiers;
private boolean trustedFinal;
// Generics and annotations support
private transient String signature;
// generic info repository; lazily initialized
@ -119,6 +120,7 @@ class Field extends AccessibleObject implements Member {
String name,
Class<?> type,
int modifiers,
boolean trustedFinal,
int slot,
String signature,
byte[] annotations)
@ -127,6 +129,7 @@ class Field extends AccessibleObject implements Member {
this.name = name;
this.type = type;
this.modifiers = modifiers;
this.trustedFinal = trustedFinal;
this.slot = slot;
this.signature = signature;
this.annotations = annotations;
@ -148,7 +151,7 @@ class Field extends AccessibleObject implements Member {
if (this.root != null)
throw new IllegalArgumentException("Can not copy a non-root Field");
Field res = new Field(clazz, name, type, modifiers, slot, signature, annotations);
Field res = new Field(clazz, name, type, modifiers, trustedFinal, slot, signature, annotations);
res.root = this;
// Might as well eagerly propagate this if already present
res.fieldAccessor = fieldAccessor;
@ -728,7 +731,9 @@ class Field extends AccessibleObject implements Member {
* this {@code Field} object;</li>
* <li>the field is non-static; and</li>
* <li>the field's declaring class is not a {@linkplain Class#isHidden()
* hidden class}.</li>
* hidden class}; and</li>
* <li>the field's declaring class is not a {@linkplain Class#isRecord()
* record class}.</li>
* </ul>
* If any of the above checks is not met, this method throws an
* {@code IllegalAccessException}.
@ -1145,10 +1150,14 @@ class Field extends AccessibleObject implements Member {
}
@Override
Field getRoot() {
/* package-private */ Field getRoot() {
return root;
}
/* package-private */ boolean isTrustedFinal() {
return trustedFinal;
}
/**
* {@inheritDoc}
*

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2020, 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
@ -118,6 +118,10 @@ class ReflectAccess implements jdk.internal.access.JavaLangReflectAccess {
return (T) obj.getRoot();
}
public boolean isTrustedFinalField(Field f) {
return f.isTrustedFinal();
}
public <T> T newInstance(Constructor<T> ctor, Object[] args, Class<?> caller)
throws IllegalAccessException, InstantiationException, InvocationTargetException
{

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2020, 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
@ -96,6 +96,9 @@ public interface JavaLangReflectAccess {
/** Gets the root of the given AccessibleObject object; null if arg is the root */
public <T extends AccessibleObject> T getRoot(T obj);
/** Tests if this is a trusted final field */
public boolean isTrustedFinalField(Field f);
/** Returns a new instance created by the given constructor with access check */
public <T> T newInstance(Constructor<T> ctor, Object[] args, Class<?> caller)
throws IllegalAccessException, InstantiationException, InvocationTargetException;

@ -31,6 +31,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.access.SharedSecrets;
import jdk.internal.misc.VM;
/** Common utility routines used by both java.lang and
@ -336,6 +337,14 @@ public class Reflection {
return false;
}
/*
* Tests if the given Field is a trusted final field and it cannot be
* modified reflectively regardless of the value of its accessible flag.
*/
public static boolean isTrustedFinalField(Field field) {
return SharedSecrets.getJavaLangReflectAccess().isTrustedFinalField(field);
}
/**
* Returns an IllegalAccessException with an exception message based on
* the access that is denied.

@ -181,7 +181,9 @@ public class ReflectionFactory {
field = root;
}
}
return UnsafeFieldAccessorFactory.newFieldAccessor(field, override);
boolean isFinal = Modifier.isFinal(field.getModifiers());
boolean isReadOnly = isFinal && (!override || langReflectAccess.isTrustedFinalField(field));
return UnsafeFieldAccessorFactory.newFieldAccessor(field, isReadOnly);
}
public MethodAccessor newMethodAccessor(Method method) {

@ -29,13 +29,12 @@ import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
class UnsafeFieldAccessorFactory {
static FieldAccessor newFieldAccessor(Field field, boolean override) {
static FieldAccessor newFieldAccessor(Field field, boolean isReadOnly) {
Class<?> type = field.getType();
boolean isStatic = Modifier.isStatic(field.getModifiers());
boolean isFinal = Modifier.isFinal(field.getModifiers());
boolean isVolatile = Modifier.isVolatile(field.getModifiers());
boolean isQualified = isFinal || isVolatile;
boolean isReadOnly = isFinal && (isStatic || !override || field.getDeclaringClass().isHidden());
if (isStatic) {
// This code path does not guarantee that the field's
// declaring class has been initialized, but it must be

@ -234,7 +234,7 @@ java.lang.NullPointerException NullPointerException} to be thrown.
<p> The java.lang.management API is thread-safe.
@see {@linkplain javax.management JMX Specification}
@see javax.management JMX Specification
@author Mandy Chung
@since 1.5

@ -103,14 +103,14 @@ public class Logger {
}
}
public void log0(Level level, String s, Throwable e) {
private void log0(Level level, String s, Throwable e) {
if (impl.isLoggable(level)) {
var sf = WALKER.walk(f -> f.skip(2).findFirst()).get();
impl.logp(Level.FINE, sf.getClassName(), sf.getMethodName(), s, e);
}
}
public void log0(Level level, String s, Object... o) {
private void log0(Level level, String s, Object... o) {
if (impl.isLoggable(level)) {
var sf = WALKER.walk(f -> f.skip(2).findFirst()).get();
impl.logp(Level.FINE, sf.getClassName(), sf.getMethodName(),

@ -1168,7 +1168,7 @@ public class Checker extends DocTreePathScanner<Void, Void> {
return;
}
}
env.messages.warning(SYNTAX, tree, "dc.empty", tree.getKind().tagName);
env.messages.warning(MISSING, tree, "dc.empty", tree.getKind().tagName);
}
boolean hasNonWhitespace(TextTree tree) {

@ -999,7 +999,10 @@ public class LambdaToMethod extends TreeTranslator {
private JCExpression makeReceiver(VarSymbol rcvr) {
if (rcvr == null) return null;
JCExpression rcvrExpr = make.Ident(rcvr);
Type rcvrType = tree.ownerAccessible ? tree.sym.enclClass().type : tree.expr.type;
boolean protAccess =
isProtectedInSuperClassOfEnclosingClassInOtherPackage(tree.sym, owner);
Type rcvrType = tree.ownerAccessible && !protAccess ? tree.sym.enclClass().type
: tree.expr.type;
if (rcvrType == syms.arrayClass.type) {
// Map the receiver type to the actually type, not just "array"
rcvrType = tree.getQualifierExpression().type;
@ -2270,11 +2273,6 @@ public class LambdaToMethod extends TreeTranslator {
types.erasure(owner.enclClass().asType()));
}
boolean isProtectedInSuperClassOfEnclosingClassInOtherPackage() {
return ((tree.sym.flags() & PROTECTED) != 0 &&
tree.sym.packge() != owner.packge());
}
/**
* Erasure destroys the implementation parameter subtype
* relationship for intersection types.
@ -2311,7 +2309,7 @@ public class LambdaToMethod extends TreeTranslator {
needsVarArgsConversion() ||
isArrayOp() ||
(!nestmateLambdas && isPrivateInOtherClass()) ||
isProtectedInSuperClassOfEnclosingClassInOtherPackage() ||
isProtectedInSuperClassOfEnclosingClassInOtherPackage(tree.sym, owner) ||
!receiverAccessible() ||
(tree.getMode() == ReferenceMode.NEW &&
tree.kind != ReferenceKind.ARRAY_CTOR &&
@ -2386,6 +2384,12 @@ public class LambdaToMethod extends TreeTranslator {
}
}
private boolean isProtectedInSuperClassOfEnclosingClassInOtherPackage(Symbol targetReference,
Symbol currentClass) {
return ((targetReference.flags() & PROTECTED) != 0 &&
targetReference.packge() != currentClass.packge());
}
/**
* Signature Generation
*/

@ -0,0 +1,108 @@
/*
* Copyright (c) 2020, 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.javadoc.internal;
import java.util.ResourceBundle;
import static java.util.ResourceBundle.getBundle;
public final class Versions {
private Versions() { throw new AssertionError(); }
/**
* Returns the version of the {@code javadoc} tool and the Standard doclet.
*
* <p> This is typically the same as the version of the JDK platform being
* used to run the tool, but may be different when running the tool on an
* older version of the platform.
*
* @throws RuntimeException in an unlikely event of the version info
* not being available
*
* @apiNote This method does not return {@code null}, has the return type of
* {@code Optional<Runtime.Version>}, or throw a checked exception. Those
* would warp the API to cater for something that is probably a result of
* a build error anyway. Hence, {@code RuntimeException}.
*
* @return the version
*/
public static Runtime.Version javadocVersion() throws RuntimeException {
/*
* The "jdk.javadoc.internal.tool.resources.version" resource bundle is
* non-localized and represented by a class compiled from a source like this:
*
* $ cat build/.../support/gensrc/jdk.javadoc/jdk/javadoc/internal/tool/resources/version.java
* package jdk.javadoc.internal.tool.resources;
*
* public final class version extends java.util.ListResourceBundle {
* protected final Object[][] getContents() {
* return new Object[][] {
* { "full", "15-internal+0-2020-06-02-1426246.duke..." },
* { "jdk", "15" },
* { "release", "15-internal" },
* };
* }
* }
*
* The string keyed by "full" should be parseable by Runtime.Version.parse()
*/
ResourceBundle bundle = getBundle("jdk.javadoc.internal.tool.resources.version");
return Runtime.Version.parse(bundle.getString("full"));
}
/**
* Returns a short string representation of the provided version.
*
* <p> Examples of strings returned from this method are: "15" and
* "15-internal".
*
* @return a short string representation of the provided version
*
* @throws NullPointerException if {@code v == null}
*/
public static String shortVersionStringOf(Runtime.Version v) {
String svstr = String.valueOf(v.feature());
if (v.pre().isPresent()) {
svstr += "-" + v.pre().get();
}
return svstr;
}
/**
* Returns a full string representation of the provided version.
*
* <p> Examples of strings returned from this method are "14+36-1461" and
* "15-internal+0-2020-06-02-1426246.duke...".
*
* @return a full string representation of the provided version
*
* @throws NullPointerException if {@code v == null}
*/
public static String fullVersionStringOf(Runtime.Version v) {
return v.toString();
}
}

@ -27,6 +27,7 @@ package jdk.javadoc.internal.doclets.formats.html;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -105,8 +106,12 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
addHeading(uc, contentTree);
HtmlTree dl = HtmlTree.DL(HtmlStyle.index);
Map<String,Integer> duplicateLabelCheck = new HashMap<>();
memberlist.forEach(e -> duplicateLabelCheck.compute(e.getFullyQualifiedLabel(utils),
(k, v) -> v == null ? 1 : v + 1));
for (IndexItem indexItem : memberlist) {
addDescription(indexItem, dl);
addDescription(indexItem, dl,
duplicateLabelCheck.get(indexItem.getFullyQualifiedLabel(utils)) > 1);
}
contentTree.add(dl);
}
@ -120,14 +125,14 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
contentTree.add(heading);
}
protected void addDescription(IndexItem indexItem, Content dl) {
protected void addDescription(IndexItem indexItem, Content dl, boolean addModuleInfo) {
SearchIndexItem si = indexItem.getSearchTag();
if (si != null) {
addDescription(si, dl);
} else {
si = new SearchIndexItem();
si.setLabel(indexItem.getLabel());
addElementDescription(indexItem, dl, si);
addElementDescription(indexItem, dl, si, addModuleInfo);
searchItems.add(si);
}
}
@ -138,8 +143,10 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
* @param indexItem the element to be documented
* @param dlTree the content tree to which the description will be added
* @param si the search index item
* @param addModuleInfo whether to include module information
*/
protected void addElementDescription(IndexItem indexItem, Content dlTree, SearchIndexItem si) {
protected void addElementDescription(IndexItem indexItem, Content dlTree, SearchIndexItem si,
boolean addModuleInfo) {
Content dt;
Element element = indexItem.getElement();
String label = indexItem.getLabel();
@ -165,6 +172,9 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
dt = HtmlTree.DT(getLink(new LinkInfoImpl(configuration,
LinkInfoImpl.Kind.INDEX, (TypeElement)element).strong(true)));
si.setContainingPackage(utils.getPackageName(utils.containingPackage(element)));
if (configuration.showModules && addModuleInfo) {
si.setContainingModule(utils.getFullyQualifiedName(utils.containingModule(element)));
}
si.setCategory(Category.TYPES);
dt.add(" - ");
addClassInfo((TypeElement)element, dt);
@ -175,6 +185,9 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
getDocLink(LinkInfoImpl.Kind.INDEX, containingType, element, new StringContent(label))));
si.setContainingPackage(utils.getPackageName(utils.containingPackage(element)));
si.setContainingClass(utils.getSimpleName(containingType));
if (configuration.showModules && addModuleInfo) {
si.setContainingModule(utils.getFullyQualifiedName(utils.containingModule(element)));
}
if (utils.isExecutableElement(element)) {
String url = HtmlTree.encodeURL(links.getName(getAnchor((ExecutableElement)element)));
if (!label.equals(url)) {

@ -205,8 +205,6 @@ public class DeprecatedListWriter extends SubWriterHolderWriter {
private EnumMap<DeprElementKind, AbstractMemberWriter> writerMap;
private HtmlConfiguration configuration;
private final Navigation navBar;
/**
@ -218,7 +216,6 @@ public class DeprecatedListWriter extends SubWriterHolderWriter {
public DeprecatedListWriter(HtmlConfiguration configuration, DocPath filename) {
super(configuration, filename);
this.configuration = configuration;
this.navBar = new Navigation(null, configuration, PageMode.DEPRECATED, path);
NestedClassWriterImpl classW = new NestedClassWriterImpl(this);
writerMap = new EnumMap<>(DeprElementKind.class);

@ -276,7 +276,7 @@ public class HelpWriter extends HtmlDocletWriter {
HtmlTree.CODE(new StringContent(example[0])), example[1])));
}
Content searchSpecLink = HtmlTree.A(
resources.getText("doclet.help.search.spec.url", Runtime.version().feature()),
resources.getText("doclet.help.search.spec.url", configuration.getDocletVersion().feature()),
getContent("doclet.help.search.spec.title"));
Content searchRefer = HtmlTree.P(getContent("doclet.help.search.refer", searchSpecLink));
section.add(searchIntro)

@ -42,6 +42,7 @@ import jdk.javadoc.doclet.DocletEnvironment;
import jdk.javadoc.doclet.Reporter;
import jdk.javadoc.doclet.StandardDoclet;
import jdk.javadoc.doclet.Taglet;
import jdk.javadoc.internal.Versions;
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
import jdk.javadoc.internal.doclets.toolkit.DocletException;
import jdk.javadoc.internal.doclets.toolkit.Messages;
@ -51,8 +52,6 @@ import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
import static javax.tools.Diagnostic.Kind.*;
/**
* Configure the output based on the command-line options.
* <p>
@ -142,31 +141,29 @@ public class HtmlConfiguration extends BaseConfiguration {
contents = new Contents(this);
options = new HtmlOptions(this);
String v;
Runtime.Version v;
try {
// the version bundle is not localized
ResourceBundle rb = ResourceBundle.getBundle(versionBundleName, Locale.getDefault());
try {
v = rb.getString("release");
} catch (MissingResourceException e) {
v = defaultDocletVersion;
}
} catch (MissingResourceException e) {
v = defaultDocletVersion;
v = Versions.javadocVersion();
} catch (RuntimeException e) {
assert false : e;
v = Runtime.version(); // arguably, the only sensible default
}
docletVersion = v;
}
private static final String versionBundleName = "jdk.javadoc.internal.tool.resources.version";
private static final String defaultDocletVersion = System.getProperty("java.version");
public final String docletVersion;
private final Runtime.Version docletVersion;
public final Date startTime = new Date();
@Override
public String getDocletVersion() {
public Runtime.Version getDocletVersion() {
return docletVersion;
}
@Override
public String getDocletVersionString() {
return Versions.shortVersionStringOf(docletVersion);
}
@Override
public Resources getDocResources() {
return docResources;

@ -431,7 +431,7 @@ public class HtmlDocletWriter {
Content htmlComment = contents.newPage;
List<DocPath> additionalStylesheets = configuration.getAdditionalStylesheets();
additionalStylesheets.addAll(localStylesheets);
Head head = new Head(path, configuration.docletVersion, configuration.startTime)
Head head = new Head(path, configuration.getDocletVersionString(), configuration.startTime)
.setTimestamp(!options.noTimestamp())
.setDescription(description)
.setGenerator(getGenerator(getClass()))

@ -75,7 +75,7 @@ public class IndexRedirectWriter extends HtmlDocletWriter {
*/
private void generateIndexFile() throws DocFileIOException {
Content htmlComment = contents.newPage;
Head head = new Head(path, configuration.docletVersion, configuration.startTime)
Head head = new Head(path, configuration.getDocletVersionString(), configuration.startTime)
.setTimestamp(!options.noTimestamp())
.setDescription("index redirect")
.setGenerator(getGenerator(getClass()))

@ -148,6 +148,9 @@ public class SearchIndexItem {
if (!containingPackage.isEmpty()) {
item.append("\"p\":\"").append(containingPackage).append("\",");
}
if (!containingModule.isEmpty()) {
item.append("\"m\":\"").append(containingModule).append("\",");
}
item.append("\"l\":\"").append(label).append("\"");
if (!url.isEmpty()) {
item.append(",\"u\":\"").append(url).append("\"");
@ -155,8 +158,11 @@ public class SearchIndexItem {
item.append("}");
break;
case MEMBERS:
item.append("{")
.append("\"p\":\"").append(containingPackage).append("\",")
item.append("{");
if (!containingModule.isEmpty()) {
item.append("\"m\":\"").append(containingModule).append("\",");
}
item.append("\"p\":\"").append(containingPackage).append("\",")
.append("\"c\":\"").append(containingClass).append("\",")
.append("\"l\":\"").append(label).append("\"");
if (!url.isEmpty()) {

@ -235,7 +235,7 @@ public class SourceToHTMLConverter {
* @param path the path for the file.
*/
private void writeToFile(Content body, DocPath path, TypeElement te) throws DocFileIOException {
Head head = new Head(path, configuration.docletVersion, configuration.startTime)
Head head = new Head(path, configuration.getDocletVersionString(), configuration.startTime)
// .setTimestamp(!options.notimestamp) // temporary: compatibility!
.setTitle(resources.getText("doclet.Window_Source_title"))
// .setCharset(options.charset) // temporary: compatibility!

@ -34,6 +34,7 @@ var searchPattern = "";
var RANKING_THRESHOLD = 2;
var NO_MATCH = 0xffff;
var MAX_RESULTS_PER_CATEGORY = 500;
var UNNAMED = "<Unnamed>";
function escapeHtml(str) {
return str.replace(/</g, "&lt;").replace(/>/g, "&gt;");
}
@ -48,14 +49,16 @@ function getURLPrefix(ui) {
return ui.item.l + slash;
} else if (ui.item.category === catPackages && ui.item.m) {
return ui.item.m + slash;
} else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) {
$.each(packageSearchIndex, function(index, item) {
if (item.m && ui.item.p == item.l) {
urlPrefix = item.m + slash;
}
});
return urlPrefix;
} else {
} else if (ui.item.category === catTypes || ui.item.category === catMembers) {
if (ui.item.m) {
urlPrefix = ui.item.m + slash;
} else {
$.each(packageSearchIndex, function(index, item) {
if (item.m && ui.item.p === item.l) {
urlPrefix = item.m + slash;
}
});
}
return urlPrefix;
}
return urlPrefix;
@ -121,7 +124,7 @@ $.widget("custom.catcomplete", $.ui.autocomplete, {
rMenu.menu.bindings = $();
$.each(items, function(index, item) {
var li;
if (item.l !== noResult.l && item.category !== currentCategory) {
if (item.category && item.category !== currentCategory) {
ul.append("<li class=\"ui-autocomplete-category\">" + item.category + "</li>");
currentCategory = item.category;
}
@ -141,15 +144,15 @@ $.widget("custom.catcomplete", $.ui.autocomplete, {
if (item.category === catModules) {
label = getHighlightedText(item.l, matcher);
} else if (item.category === catPackages) {
label = (item.m)
? getHighlightedText(item.m + "/" + item.l, matcher)
: getHighlightedText(item.l, matcher);
label = getHighlightedText(item.l, matcher);
} else if (item.category === catTypes) {
label = (item.p)
label = (item.p && item.p !== UNNAMED)
? getHighlightedText(item.p + "." + item.l, matcher)
: getHighlightedText(item.l, matcher);
} else if (item.category === catMembers) {
label = getHighlightedText(item.p + "." + (item.c + "." + item.l), matcher);
label = (item.p && item.p !== UNNAMED)
? getHighlightedText(item.p + "." + item.c + "." + item.l, matcher)
: getHighlightedText(item.c + "." + item.l, matcher);
} else if (item.category === catSearchTags) {
label = getHighlightedText(item.l, matcher);
} else {
@ -165,7 +168,11 @@ $.widget("custom.catcomplete", $.ui.autocomplete, {
div.html(label + "<span class=\"search-tag-holder-result\"> (" + item.h + ")</span>");
}
} else {
div.html(label);
if (item.m) {
div.html(item.m + "/" + label);
} else {
div.html(label);
}
}
return li;
}
@ -317,7 +324,7 @@ $(function() {
collision: "flip"
},
select: function(event, ui) {
if (ui.item.l !== noResult.l) {
if (ui.item.category) {
var url = getURLPrefix(ui);
if (ui.item.category === catModules) {
url += "module-summary.html";
@ -330,13 +337,13 @@ $(function() {
} else if (ui.item.category === catTypes) {
if (ui.item.u) {
url = ui.item.u;
} else if (ui.item.p === "<Unnamed>") {
} else if (ui.item.p === UNNAMED) {
url += ui.item.l + ".html";
} else {
url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.l + ".html";
}
} else if (ui.item.category === catMembers) {
if (ui.item.p === "<Unnamed>") {
if (ui.item.p === UNNAMED) {
url += ui.item.c + ".html" + "#";
} else {
url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.c + ".html" + "#";

@ -144,7 +144,7 @@ doclet.help.package.intro=\
each. These pages may contain six categories:
doclet.help.module.intro=\
Each module has a page that contains a list of its packages, dependencies on other modules, \
and services, with a summary for each. These page may contain three categories:
and services, with a summary for each. These pages may contain three categories:
doclet.help.class_interface.head=\
Class or Interface
doclet.help.class_interface.intro=\
@ -164,7 +164,6 @@ doclet.help.class_interface.declaration=\
doclet.help.class_interface.description=\
Class or Interface Description
doclet.help.class_interface.summary=\
Each summary entry contains the first sentence from the detailed description for that item. \
The summary entries are alphabetical, while the detailed descriptions are in the order they \
appear in the source code. This preserves the logical groupings established by the programmer.
doclet.help.use.head=\
@ -189,7 +188,7 @@ doclet.help.tree.package=\
hierarchy for only that package.
doclet.help.deprecated.body=\
The {0} page lists all of the API that have been deprecated. A deprecated API is not \
recommended for use, generally due to improvements, and a replacement API is usually given. \
recommended for use, generally due to shortcomings, and a replacement API is usually given. \
Deprecated APIs may be removed in future implementations.
doclet.help.index.head=\
Index
@ -198,9 +197,9 @@ doclet.help.index.body=\
and fields, as well as lists of all packages and all classes.
doclet.help.serial_form.body=\
Each serializable or externalizable class has a description of its serialization fields and \
methods. This information is of interest to re-implementors, not to developers using the API. \
methods. This information is of interest to those who implement rather than use the API. \
While there is no link in the navigation bar, you can get to this information by going to any \
serialized class and clicking "Serialized Form" in the "See also" section of the class \
serialized class and clicking "Serialized Form" in the "See Also" section of the class \
description.
doclet.help.constants.body=\
The {0} page lists the static final fields and their values.

@ -151,11 +151,19 @@ public abstract class BaseConfiguration {
public abstract Resources getDocResources();
/**
* Returns a string identifying the version of the doclet.
* Returns the version of the {@link #doclet doclet}.
*
* @return a version string
* @return the version
*/
public abstract String getDocletVersion();
public abstract Runtime.Version getDocletVersion();
/**
* Returns a short string representation of the version returned by
* {@linkplain #getDocletVersion()}.
*
* @return a short string representation of the version
*/
public abstract String getDocletVersionString();
/**
* This method should be defined in all those doclets (configurations),

@ -139,9 +139,15 @@ public class Comparators {
@Override
public int compare(Element e1, Element e2) {
int result = compareFullyQualifiedNames(e1, e2);
if (result == 0)
result = compareModuleNames(e1, e2);
return result;
if (result != 0) {
return result;
}
// if elements are executable compare their parameter arrays
result = compareParameters(e1, e2);
if (result != 0) {
return result;
}
return compareModuleNames(e1, e2);
}
};
}
@ -256,19 +262,11 @@ public class Comparators {
if (result != 0) {
return result;
}
// if element kinds are the same, and are methods,
// compare the method parameters
if (hasParameters(e1)) {
List<? extends VariableElement> parameters1 = ((ExecutableElement)e1).getParameters();
List<? extends VariableElement> parameters2 = ((ExecutableElement)e2).getParameters();
result = compareParameters(false, parameters1, parameters2);
if (result != 0) {
return result;
}
result = compareParameters(true, parameters1, parameters2);
if (result != 0) {
return result;
}
// if element kinds are the same, and are executable,
// compare the parameter arrays
result = compareParameters(e1, e2);
if (result != 0) {
return result;
}
// else fall back on fully qualified names
result = compareFullyQualifiedNames(e1, e2);
@ -383,15 +381,7 @@ public class Comparators {
if (result != 0) {
return result;
}
if (hasParameters(e1) && hasParameters(e2)) {
List<? extends VariableElement> parameters1 = ((ExecutableElement)e1).getParameters();
List<? extends VariableElement> parameters2 = ((ExecutableElement)e2).getParameters();
result = compareParameters(false, parameters1, parameters2);
if (result != 0) {
return result;
}
result = compareParameters(true, parameters1, parameters2);
}
result = compareParameters(e1, e2);
if (result != 0) {
return result;
}
@ -504,6 +494,34 @@ public class Comparators {
return 0;
}
/**
* Compares the parameter arrays of two elements if they both are executable.
* @param e1 the first element
* @param e2 the second element
* @return a negative integer, zero, or a positive integer as the first
* argument is less than, equal to, or greater than the second
*/
protected int compareParameters(Element e1, Element e2) {
int result = 0;
if (hasParameters(e1) && hasParameters(e2)) {
List<? extends VariableElement> parameters1 = ((ExecutableElement)e1).getParameters();
List<? extends VariableElement> parameters2 = ((ExecutableElement)e2).getParameters();
result = compareParameters(false, parameters1, parameters2);
if (result != 0) {
return result;
}
result = compareParameters(true, parameters1, parameters2);
}
return result;
}
/**
* Compares the kinds of two elements.
* @param e1 the first element
* @param e2 the second element
* @return a negative integer, zero, or a positive integer as the first
* argument is less than, equal to, or greater than the second
*/
protected int compareElementKinds(Element e1, Element e2) {
return Integer.compare(getKindIndex(e1), getKindIndex(e2));
}

@ -26,7 +26,6 @@
package jdk.javadoc.internal.doclets.toolkit.util;
import jdk.javadoc.internal.doclets.formats.html.SearchIndexItem;
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
@ -90,6 +89,16 @@ public class IndexItem {
return label;
}
public String getFullyQualifiedLabel(Utils utils) {
if (typeElement != null) {
return utils.getFullyQualifiedName(typeElement) + "." + label;
} else if (element != null) {
return utils.getFullyQualifiedName(element);
} else {
return label;
}
}
public Element getElement() {
return element;
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2020, 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
@ -109,6 +109,7 @@ public abstract class LinkFactory {
@Override
public Content visitWildcard(WildcardType type, LinkInfo linkInfo) {
linkInfo.isTypeBound = true;
link.add(getTypeAnnotationLinks(linkInfo));
link.add("?");
TypeMirror extendsBound = type.getExtendsBound();
if (extendsBound != null) {

@ -31,16 +31,14 @@ import java.io.PrintWriter;
import java.text.BreakIterator;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.IllformedLocaleException;
import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.Objects;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import javax.tools.JavaFileManager;
@ -62,6 +60,7 @@ import jdk.javadoc.doclet.Doclet;
import jdk.javadoc.doclet.Doclet.Option;
import jdk.javadoc.doclet.DocletEnvironment;
import jdk.javadoc.doclet.StandardDoclet;
import jdk.javadoc.internal.Versions;
import jdk.javadoc.internal.tool.Main.Result;
import jdk.javadoc.internal.tool.ToolOptions.ToolOption;
@ -167,17 +166,30 @@ public class Start {
@Override
public void version() {
showVersion("javadoc.version", "release");
showVersion("javadoc.version", orDefault(() -> Versions.shortVersionStringOf(toolVersion())));
}
@Override
public void fullVersion() {
showVersion("javadoc.fullversion", "full");
showVersion("javadoc.fullversion", orDefault(() -> Versions.fullVersionStringOf(toolVersion())));
}
private String orDefault(Supplier<String> s) {
try {
return s.get();
} catch (RuntimeException e) {
assert false : e;
return Log.getLocalizedString("version.not.available");
}
}
};
return new ToolOptions(context, messager, helper);
}
private Runtime.Version toolVersion() {
return Versions.javadocVersion();
}
private void showUsage() {
showUsage("main.usage", ToolOption.Kind.STANDARD, "main.usage.foot");
}
@ -196,26 +208,8 @@ public class Start {
messager.notice(footerKey);
}
private static final String versionRBName = "jdk.javadoc.internal.tool.resources.version";
private static ResourceBundle versionRB;
private void showVersion(String labelKey, String versionKey) {
messager.notice(labelKey, messager.programName, getVersion(versionKey));
}
private static String getVersion(String key) {
if (versionRB == null) {
try {
versionRB = ResourceBundle.getBundle(versionRBName);
} catch (MissingResourceException e) {
return Log.getLocalizedString("version.not.available");
}
}
try {
return versionRB.getString(key);
} catch (MissingResourceException e) {
return Log.getLocalizedString("version.not.available");
}
private void showVersion(String labelKey, String value) {
messager.notice(labelKey, messager.programName, value);
}
private void showToolOptions(ToolOption.Kind kind) {

@ -152,7 +152,7 @@ public interface Type extends Mirror {
* Returns the name of this type. The result is of the same form as
* the name returned by {@link Class#getName()}.
* The returned name may not be a
* <a href="${docRoot}/java.base/java/lang/ClassLoader.html#binary-name">binary name</a>.
* <a href="{@docRoot}/java.base/java/lang/ClassLoader.html#binary-name">binary name</a>.
*
* @return the name of this type
*/

@ -44,7 +44,7 @@ public interface ClassUnloadEvent extends Event {
/**
* Returns the {@linkplain com.sun.jdi.Type#name() name of the class}
* that has been unloaded. The returned string may not be a
* <a href="${docRoot}/java.base/java/lang/ClassLoader.html#binary-name">binary name</a>.
* <a href="{@docRoot}/java.base/java/lang/ClassLoader.html#binary-name">binary name</a>.
*
* @see Class#getName()
*/

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, 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
@ -34,6 +34,7 @@ import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.URI;
import java.nio.charset.Charset;
import java.time.Instant;
import java.util.ArrayList;
@ -50,6 +51,9 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import jdk.internal.shellsupport.doc.JavadocFormatter;
import jdk.internal.jshell.tool.StopDetectingInputStream.State;
@ -974,6 +978,15 @@ class ConsoleIOContext extends IOContext {
int pendingBraces = 0;
com.sun.tools.javac.util.Context ctx =
new com.sun.tools.javac.util.Context();
SimpleJavaFileObject source = new SimpleJavaFileObject(URI.create("mem://snippet"),
JavaFileObject.Kind.SOURCE) {
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return code;
}
};
ctx.put(DiagnosticListener.class, d -> {});
com.sun.tools.javac.util.Log.instance(ctx).useSource(source);
com.sun.tools.javac.parser.ScannerFactory scannerFactory =
com.sun.tools.javac.parser.ScannerFactory.instance(ctx);
com.sun.tools.javac.parser.Scanner scanner =

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2020, 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
@ -636,13 +636,18 @@ public final class Unsafe {
* @see #getInt(Object, long)
*/
@ForceInline
@SuppressWarnings("preview")
public long objectFieldOffset(Field f) {
if (f == null) {
throw new NullPointerException();
}
if (f.getDeclaringClass().isHidden()) {
Class<?> declaringClass = f.getDeclaringClass();
if (declaringClass.isHidden()) {
throw new UnsupportedOperationException("can't get field offset on a hidden class: " + f);
}
if (declaringClass.isRecord()) {
throw new UnsupportedOperationException("can't get field offset on a record (preview): " + f);
}
return theInternalUnsafe.objectFieldOffset(f);
}
@ -664,13 +669,18 @@ public final class Unsafe {
* @see #getInt(Object, long)
*/
@ForceInline
@SuppressWarnings("preview")
public long staticFieldOffset(Field f) {
if (f == null) {
throw new NullPointerException();
}
if (f.getDeclaringClass().isHidden()) {
Class<?> declaringClass = f.getDeclaringClass();
if (declaringClass.isHidden()) {
throw new UnsupportedOperationException("can't get field offset on a hidden class: " + f);
}
if (declaringClass.isRecord()) {
throw new UnsupportedOperationException("can't get field offset on a record (preview): " + f);
}
return theInternalUnsafe.staticFieldOffset(f);
}
@ -685,13 +695,18 @@ public final class Unsafe {
* this class.
*/
@ForceInline
@SuppressWarnings("preview")
public Object staticFieldBase(Field f) {
if (f == null) {
throw new NullPointerException();
}
if (f.getDeclaringClass().isHidden()) {
Class<?> declaringClass = f.getDeclaringClass();
if (declaringClass.isHidden()) {
throw new UnsupportedOperationException("can't get base address on a hidden class: " + f);
}
if (declaringClass.isRecord()) {
throw new UnsupportedOperationException("can't get base address on a record (preview): " + f);
}
return theInternalUnsafe.staticFieldBase(f);
}

@ -234,9 +234,9 @@ import java.util.Set;
* <td>null/unset</td>
* <td>
* A value representing the version entry to use when accessing a
* <a href=="{@docRoot}/../specs/jar/jar.html#multi-release-jar-files">
* <a href="{@docRoot}/../specs/jar/jar.html#multi-release-jar-files">
* multi-release JAR</a>. If the JAR is not a
* <a href=="{@docRoot}/../specs/jar/jar.html#multi-release-jar-files">
* <a href="{@docRoot}/../specs/jar/jar.html#multi-release-jar-files">
* multi-release JAR</a>, the value will be ignored and the JAR will be
* considered un-versioned.
* <p>

@ -0,0 +1,81 @@
/*
* Copyright (c) 2020, 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.
*
* 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.
*/
/*
* @test
* @bug 8237950
* @summary Test very long chain of StringBuilder append calls.
* @run main/othervm -Xbatch compiler.stringopts.TestLongStringConcat
*/
package compiler.stringopts;
public class TestLongStringConcat {
public static String test() {
return (new StringBuilder("")).append("1").append("2").append("3").append("4").
append("5").append("6").append("7").append("8").append("9").append("10").
append("11").append("12").append("13").append("14").append("15").append("16").
append("17").append("18").append("19").append("20").append("21").append("22").
append("23").append("24").append("25").append("26").append("27").append("28").
append("29").append("30").append("31").append("32").append("33").append("34").
append("35").append("36").append("37").append("38").append("39").append("40").
append("41").append("42").append("43").append("44").append("45").append("46").
append("47").append("48").append("49").append("50").append("51").append("52").
append("53").append("54").append("55").append("56").append("57").append("58").
append("59").append("60").append("61").append("62").append("63").append("64").
append("65").append("66").append("67").append("68").append("69").append("70").
append("71").append("72").append("73").append("74").append("75").append("76").
append("77").append("78").append("79").append("80").append("81").append("82").
append("83").append("84").append("85").append("86").append("87").append("88").
append("89").append("90").append("91").append("92").append("93").append("94").
append("95").append("96").append("97").append("98").append("99").append("100").
append("101").append("102").append("103").append("104").append("105").
append("106").append("107").append("108").append("109").append("110").
append("111").append("112").append("113").append("114").append("115").
append("116").append("117").append("118").append("119").append("120").
append("121").append("122").append("123").append("124").append("125").
append("126").append("127").append("128").append("129").append("130").
append("131").append("132").append("133").append("134").append("135").
append("136").append("137").append("138").append("139").append("140").
append("141").append("142").append("143").append("144").append("145").
append("146").append("147").append("148").append("149").append("150").
append("151").append("152").append("153").append("154").append("155").
append("156").append("157").append("158").append("159").append("160").
append("161").append("162").append("163").append("164").append("165").
append("166").append("167").append("168").append("169").append("170").
append("171").append("172").append("173").append("174").append("175").
append("176").append("177").append("178").append("179").append("180").
append("181").append("182").append("183").append("184").append("185").
append("186").append("187").append("188").append("189").append("190").
append("191").append("192").append("193").append("194").append("195").
append("196").append("197").append("198").append("199").append("200").
toString();
}
public static void main(String[] args) {
for (int i = 0; i < 100_000; ++i) {
test();
}
}
}

@ -1,6 +1,6 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019 SAP SE. All rights reserved.
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2020 SAP SE. 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
@ -24,12 +24,12 @@
/**
* @test
* @summary Test that the default of flag ShowCodeDetailsInExceptionMessages is 'false',
* i.e., make sure the VM does not print the message on default.
* @summary Test that the default of flag ShowCodeDetailsInExceptionMessages is 'true',
* i.e., make sure the VM does print the message by default.
* @bug 8218628
* @library /test/lib
* @compile -g SuppressMessagesTest.java
* @run main/othervm SuppressMessagesTest noMessage
* @run main/othervm SuppressMessagesTest printMessage
*/
/**
* @test

@ -1,2 +1,2 @@
Exception thrown.
java.lang.NullPointerException
java.lang.NullPointerException: Cannot enter synchronized block because "<local1>" is null

@ -0,0 +1,24 @@
#
# Copyright (c) 2020, 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.
#
# 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.
#
enablePreview=true

@ -23,9 +23,10 @@
/**
* @test
* @compile src/Fields.java
* @run testng/othervm UnreflectTest
* @summary Test Lookup::unreflectSetter and Lookup::unreflectVarHandle
* @bug 8238358 8247444
* @run testng/othervm --enable-preview UnreflectTest
* @summary Test Lookup::unreflectSetter and Lookup::unreflectVarHandle on
* trusted final fields (declared in hidden classes and records)
*/
import java.io.IOException;
@ -89,6 +90,24 @@ public class UnreflectTest {
readWriteAccessibleObject(hiddenClass, "NON_FINAL", o, false);
}
static record TestRecord(int i) {
static final Object STATIC_FINAL = new Object();
static Object STATIC_NON_FINAL = new Object();
}
/*
* Test Lookup::unreflectSetter and Lookup::unreflectVarHandle that
* cannot write the value of a non-static final field in a record class
*/
@SuppressWarnings("preview")
public void testFieldsInRecordClass() throws Throwable {
assertTrue(TestRecord.class.isRecord());
Object o = new TestRecord(1);
readOnlyAccessibleObject(TestRecord.class, "STATIC_FINAL", null, true);
readWriteAccessibleObject(TestRecord.class, "STATIC_NON_FINAL", null, false);
readOnlyAccessibleObject(TestRecord.class, "i", o, true);
}
/*
* Verify read-only access via unreflectSetter and unreflectVarHandle
*/

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2020, 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
@ -23,7 +23,7 @@
/*
* @test
* @bug 8235369 8235550
* @bug 8235369 8235550 8247444
* @summary reflection test for records
* @compile --enable-preview -source ${jdk.version} RecordReflectionTest.java
* @run testng/othervm --enable-preview RecordReflectionTest
@ -187,4 +187,19 @@ public class RecordReflectionTest {
assertEquals(f.getAnnotatedType().getAnnotations().length, 1);
assertEquals(f.getAnnotatedType().getAnnotations()[0].toString(), annos[0].toString());
}
public void testReadOnlyFieldInRecord() throws Throwable {
R2 o = new R2(1, 2);
Class<?> recordClass = R2.class;
String fieldName = "i";
Field f = recordClass.getDeclaredField(fieldName);
assertTrue(f.trySetAccessible());
assertTrue(f.get(o) != null);
try {
f.set(o, null);
assertTrue(false, "should fail to set " + fieldName);
} catch (IllegalAccessException e) {
}
}
}

@ -22,10 +22,12 @@
*/
/* @test
* @bug 8238358 8247444
* @summary Ensure that sun.misc.Unsafe::objectFieldOffset and staticFieldOffset
* throw UnsupportedOperationException on Field of a hidden class
* throw UnsupportedOperationException on Field of a hidden or record class
* @modules jdk.unsupported
* @run main UnsafeFieldOffsets
* @compile --enable-preview -source ${jdk.version} UnsafeFieldOffsets.java
* @run testng/othervm --enable-preview UnsafeFieldOffsets
*/
import sun.misc.Unsafe;
@ -38,6 +40,9 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
public class UnsafeFieldOffsets {
static class Fields {
static final Object STATIC_FINAL = new Object();
@ -45,9 +50,14 @@ public class UnsafeFieldOffsets {
final Object FINAL = new Object();
Object NON_FINAL = new Object();
}
record TestRecord(int i) {
static final Object STATIC_FINAL = new Object();
static Object STATIC_NON_FINAL = new Object();
}
private static Unsafe UNSAFE = getUnsafe();
private static final Class<?> HIDDEN_CLASS = defineHiddenClass();
private static final Class<?> RECORD_CLASS = TestRecord.class;
private static Unsafe getUnsafe() {
try {
@ -65,7 +75,7 @@ public class UnsafeFieldOffsets {
try {
byte[] bytes = Files.readAllBytes(cf);
Class<?> c = MethodHandles.lookup().defineHiddenClass(bytes, true).lookupClass();
assertHiddenClass(c);
assertTrue(c.isHidden());
return c;
} catch (IOException e) {
throw new UncheckedIOException(e);
@ -74,13 +84,8 @@ public class UnsafeFieldOffsets {
}
}
public static void main(String[] args) throws Exception {
// non-hidden class
testStaticField(Fields.class, "STATIC_FINAL");
testStaticField(Fields.class, "STATIC_NON_FINAL");
testInstanceField(Fields.class, "FINAL");
testInstanceField(Fields.class, "NON_FINAL");
@Test
public void testNormalClass() throws Throwable {
// hidden class
testStaticField(HIDDEN_CLASS, "STATIC_FINAL");
testStaticField(HIDDEN_CLASS, "STATIC_NON_FINAL");
@ -88,13 +93,30 @@ public class UnsafeFieldOffsets {
testInstanceField(HIDDEN_CLASS, "NON_FINAL");
}
@Test
public void testHiddenClass() throws Throwable {
// hidden class
testStaticField(HIDDEN_CLASS, "STATIC_FINAL");
testStaticField(HIDDEN_CLASS, "STATIC_NON_FINAL");
testInstanceField(HIDDEN_CLASS, "FINAL");
testInstanceField(HIDDEN_CLASS, "NON_FINAL");
}
@Test
public void testRecordClass() throws Throwable {
// record class
testRecordStaticField(RECORD_CLASS, "STATIC_FINAL");
testRecordStaticField(RECORD_CLASS, "STATIC_NON_FINAL");
testRecordInstanceField(RECORD_CLASS, "i");
}
private static void testStaticField(Class<?> c, String name) throws Exception {
Field f = c.getDeclaredField(name);
try {
UNSAFE.staticFieldOffset(f);
assertNonHiddenClass(c);
assertFalse(c.isHidden(), "Expected UOE thrown: " + c);
} catch (UnsupportedOperationException e) {
assertHiddenClass(c);
assertTrue(c.isHidden(), "Expected hidden class: " + c);
}
}
@ -102,19 +124,31 @@ public class UnsafeFieldOffsets {
Field f = c.getDeclaredField(name);
try {
UNSAFE.objectFieldOffset(f);
assertNonHiddenClass(c);
assertFalse(c.isHidden(), "Expected UOE thrown: " + c);
} catch (UnsupportedOperationException e) {
assertHiddenClass(c);
assertTrue(c.isHidden(), "Expected hidden class: " + c);
}
}
private static void assertNonHiddenClass(Class<?> c) {
if (c.isHidden())
throw new RuntimeException("Expected UOE but not thrown: " + c);
@SuppressWarnings("preview")
private static void testRecordStaticField(Class<?> c, String name) throws Exception {
Field f = c.getDeclaredField(name);
try {
UNSAFE.staticFieldOffset(f);
assertFalse(c.isRecord(), "Expected UOE thrown: " + c);
} catch (UnsupportedOperationException e) {
assertTrue(c.isRecord(), "Expected record class: " + c);
}
}
private static void assertHiddenClass(Class<?> c) {
if (!c.isHidden())
throw new RuntimeException("Expected hidden class but is not: " + c);
@SuppressWarnings("preview")
private static void testRecordInstanceField(Class<?> c, String name) throws Exception {
Field f = c.getDeclaredField(name);
try {
UNSAFE.objectFieldOffset(f);
assertFalse(c.isRecord(), "Expected UOE thrown: " + c);
} catch (UnsupportedOperationException e) {
assertTrue(c.isRecord(), "Expected record class: " + c);
}
}
}

@ -24,7 +24,7 @@
/*
* @test
* @bug 4927552 8026567 8071982 8162674 8175200 8175218 8183511 8186332
* 8169819 8074407 8191030 8182765 8184205
* 8169819 8074407 8191030 8182765 8184205 8243533
* @summary test generated docs for deprecated items
* @library ../../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool
@ -164,9 +164,28 @@ public class TestDeprecatedDocs extends JavadocTester {
</td>""",
"""
<td class="col-last">
<div class="block"><span class="deprecated-label">Deprecated.</span>
<div class="block"><span class="deprecated-label">Deprecated, for removal: This \
API element is subject to removal in a future version.</span>
<div class="deprecation-comment">class_test4 passes.</div>
</div>
</td>""",
"""
<td class="col-last">
<div class="block"><span class="deprecated-label">Deprecated.</span>
<div class="deprecation-comment">class_test5 passes.</div>
</div>
</td>""",
"""
<td class="col-last">
<div class="block"><span class="deprecated-label">Deprecated.</span>
<div class="deprecation-comment">class_test6 passes.</div>
</div>
</td>""",
"""
<td class="col-last">
<div class="block"><span class="deprecated-label">Deprecated.</span>
<div class="deprecation-comment">class_test7 passes.</div>
</div>
</td>""");
checkOutput("pkg/TestClass.html", false,
@ -355,6 +374,78 @@ public class TestDeprecatedDocs extends JavadocTester {
</tr>
</tbody>
</table>
</div>""");
</div>""",
"""
<div class="deprecated-summary" id="method">
<table class="summary-table">
<caption><span>Methods</span></caption>
<thead>
<tr>
<th class="col-first" scope="col">Method</th>
<th class="col-last" scope="col">Description</th>
</tr>
</thead>
<tbody>
<tr class="alt-color">
<th class="col-deprecated-item-name" scope="row"><a href="pkg/DeprecatedClassByAnnotation.html#method()">pkg.DeprecatedClassByAnnotation.method()</a></th>
<td class="col-last"></td>
</tr>
<tr class="row-color">
<th class="col-deprecated-item-name" scope="row"><a href="pkg/TestAnnotationType.html#optional()">pkg.TestAnnotationType.optional()</a></th>
<td class="col-last">
<div class="deprecation-comment">annotation_test2 passes.</div>
</td>
</tr>
<tr class="alt-color">
<th class="col-deprecated-item-name" scope="row"><a href="pkg/TestAnnotationType.html#required()">pkg.TestAnnotationType.required()</a></th>
<td class="col-last">
<div class="deprecation-comment">annotation_test3 passes.</div>
</td>
</tr>
<tr class="row-color">
<th class="col-deprecated-item-name" scope="row"><a href="pkg/TestClass.html#method()">pkg.TestClass.method()</a></th>
<td class="col-last">
<div class="deprecation-comment">class_test5 passes. This is the second sentence of deprecated description for a method.</div>
</td>
</tr>
<tr class="alt-color">
<th class="col-deprecated-item-name" scope="row"><a href="pkg/TestClass.html#overloadedMethod(int)">pkg.TestClass.overloadedMethod&#8203;(int)</a></th>
<td class="col-last">
<div class="deprecation-comment">class_test7 passes. Overloaded method 2.</div>
</td>
</tr>
<tr class="row-color">
<th class="col-deprecated-item-name" scope="row"><a href="pkg/TestClass.html#overloadedMethod(java.lang.String)">pkg.TestClass.overloadedMethod&#8203;(String)</a></th>
<td class="col-last">
<div class="deprecation-comment">class_test6 passes. Overloaded method 1.</div>
</td>
</tr>""",
"""
<div class="deprecated-summary" id="constructor">
<table class="summary-table">
<caption><span>Constructors</span></caption>
<thead>
<tr>
<th class="col-first" scope="col">Constructor</th>
<th class="col-last" scope="col">Description</th>
</tr>
</thead>
<tbody>
<tr class="alt-color">
<th class="col-deprecated-item-name" scope="row"><a href="pkg/DeprecatedClassByAnnotation.html#%3Cinit%3E()">pkg.DeprecatedClassByAnnotation()</a></th>
<td class="col-last"></td>
</tr>
<tr class="row-color">
<th class="col-deprecated-item-name" scope="row"><a href="pkg/TestClass.html#%3Cinit%3E()">pkg.TestClass()</a></th>
<td class="col-last">
<div class="deprecation-comment">class_test3 passes. This is the second sentence of deprecated description for a constructor.</div>
</td>
</tr>
<tr class="alt-color">
<th class="col-deprecated-item-name" scope="row"><a href="pkg/TestClass.html#%3Cinit%3E(java.lang.String)">pkg.TestClass&#8203;(String)</a></th>
<td class="col-last">
<div class="deprecation-comment">class_test4 passes. Overloaded constructor.</div>
</td>
</tr>""");
}
}

@ -41,7 +41,23 @@ public class TestClass {
public TestClass() {}
/**
* @deprecated class_test4 passes. This is the second sentence of deprecated description for a method.
* @deprecated class_test4 passes. Overloaded constructor.
*/
@Deprecated(forRemoval=true)
public TestClass(String s) {}
/**
* @deprecated class_test5 passes. This is the second sentence of deprecated description for a method.
*/
public void method() {}
/**
* @deprecated class_test6 passes. Overloaded method 1.
*/
public void overloadedMethod(String s) {}
/**
* @deprecated class_test7 passes. Overloaded method 2.
*/
public void overloadedMethod(int i) {}
}

@ -0,0 +1,98 @@
/*
* Copyright (c) 2020, 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.
*
* 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.
*/
/*
* @test
* @bug 8246078
* @library ../../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool
* @build javadoc.tester.*
* @run main TestHelpPage
*/
import javadoc.tester.JavadocTester;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TestHelpPage extends JavadocTester {
public static void main(String... args) throws Exception {
TestHelpPage tester = new TestHelpPage();
tester.runTests();
}
@Test
public void test() {
setOutputDirectoryCheck(DirectoryCheck.NONE);
setAutomaticCheckLinks(false);
setAutomaticCheckAccessibility(false);
javadoc("--version");
List<String> lines = getOutputLines(Output.OUT);
System.out.println("lines: " + Arrays.toString(lines.toArray()));
String firstLine = lines.get(0);
Matcher m = Pattern.compile("javadoc\\s+(.*)").matcher(firstLine);
m.matches();
String vstr = m.group(1);
System.out.printf("vstr='%s'%n", vstr);
Runtime.Version v = Runtime.Version.parse(vstr);
System.out.printf("v=%s, v.feature()=%s%n", v, v.feature());
javadoc("-d", "out",
"-sourcepath", testSrc,
testSrc("TestHelpPage.java"));
checkExit(Exit.OK);
checking("Reference to a particular version");
Pattern searchSpecLink = Pattern.compile(
"\\Q<a href=\"https://docs.oracle.com/en/java/javase/\\E(\\d+)\\Q/docs/specs/javadoc/javadoc-search-spec.html\">\\E");
String helpContents = readOutputFile("help-doc.html");
Matcher m2 = searchSpecLink.matcher(helpContents);
if (!m2.find()) {
failed("Reference not found: " + helpContents);
return;
}
if (!String.valueOf(v.feature()).equals(m2.group(1))) {
failed("Reference to a wrong version: " + m2.group(1));
return;
}
boolean foundMore = false;
while (m2.find()) {
// print all found before failing
foundMore = true;
System.out.println(m2.group(0));
}
if (foundMore) {
failed("Multiple references: " + helpContents);
} else {
passed("All good");
}
}
}

@ -23,7 +23,7 @@
/*
* @test
* @bug 8178070 8196201 8184205 8246429
* @bug 8178070 8196201 8184205 8246429 8198705
* @summary Test packages table in module summary pages
* @library /tools/lib ../../lib
* @modules jdk.compiler/com.sun.tools.javac.api
@ -167,6 +167,14 @@ public class TestModulePackages extends JavadocTester {
<div class="sub-title"><span class="module-label-in-type">Module</span>&nbsp;<a href="../module-summary.html">o</a></div>
<div class="sub-title"><span class="package-label-in-type">Package</span>&nbsp;<a href="package-summary.html">p</a></div>
""");
checkOutput("type-search-index.js", true,
"""
{"p":"p","m":"m","l":"C"},{"p":"p","m":"o","l":"C"}""");
checkOutput("member-search-index.js", true,
"""
{"m":"m","p":"p","c":"C","l":"C()","u":"%3Cinit%3E()"}""",
"""
{"m":"o","p":"p","c":"C","l":"C()","u":"%3Cinit%3E()"}""");
}
@Test

@ -726,14 +726,16 @@ public class TestSearch extends JavadocTester {
return ui.item.l + slash;
} else if (ui.item.category === catPackages && ui.item.m) {
return ui.item.m + slash;
} else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) {
$.each(packageSearchIndex, function(index, item) {
if (item.m && ui.item.p == item.l) {
urlPrefix = item.m + slash;
}
});
return urlPrefix;
} else {
} else if (ui.item.category === catTypes || ui.item.category === catMembers) {
if (ui.item.m) {
urlPrefix = ui.item.m + slash;
} else {
$.each(packageSearchIndex, function(index, item) {
if (item.m && ui.item.p === item.l) {
urlPrefix = item.m + slash;
}
});
}
return urlPrefix;
}
return urlPrefix;

@ -24,7 +24,7 @@
/*
* @test
* @bug 8005091 8009686 8025633 8026567 6469562 8071982 8071984 8162363 8175200 8186332 8182765
* 8187288
* 8187288 8241969
* @summary Make sure that type annotations are displayed correctly
* @library ../../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool
@ -335,6 +335,35 @@ public class TestTypeAnnotations extends JavadocTester {
tation in typeannos">@WldB</a>("m") java.lang.String&gt;</span>&nbsp;<span class\
="member-name">returnWcExtends</span>()</div>""");
checkOutput("typeannos/SelfTest.html", true,
"""
<div class="member-signature"><span class="return-type"><a href="MyList.html" ti\
tle="class in typeannos">MyList</a>&lt;<a href="WldA.html" title="annotation in \
typeannos">@WldA</a> ?&gt;</span>&nbsp;<span class="member-name">returnWcExtends\
</span>()</div>""",
"""
<div class="member-signature"><span class="return-type"><a href="MyList.html" ti\
tle="class in typeannos">MyList</a>&lt;<a href="WldA.html" title="annotation in \
typeannos">@WldA</a> ? extends <a href="WldA.html" title="annotation in typeanno\
s">@WldA</a> <a href="MyList.html" title="class in typeannos">MyList</a>&lt;<a h\
ref="WldB.html" title="annotation in typeannos">@WldB</a>("m") ?&gt;&gt;</span>&\
nbsp;<span class="member-name">complex</span>()</div>""");
checkOutput("typeannos/SelfWithValue.html", true,
"""
<div class="member-signature"><span class="return-type"><a href="MyList.html" ti\
tle="class in typeannos">MyList</a>&lt;<a href="WldB.html" title="annotation in \
typeannos">@WldB</a>("m") ?&gt;</span>&nbsp;<span class="member-name">returnWcEx\
tends</span>()</div>""",
"""
<div class="member-signature"><span class="return-type"><a href="MyList.html" ti\
tle="class in typeannos">MyList</a>&lt;<a href="WldB.html" title="annotation in \
typeannos">@WldB</a>("m") ? extends <a href="MyList.html" title="class in typean\
nos">MyList</a>&lt;<a href="WldB.html" title="annotation in typeannos">@WldB</a>\
("m") ? super java.lang.String&gt;&gt;</span>&nbsp;<span class="member-name">com\
plex</span>()</div>""");
// Test for receiver annotations (Receivers.java).
checkOutput("typeannos/DefaultUnmodified.html", true,
"""

@ -23,7 +23,7 @@
/*
* @test
* @bug 8004834 8007610 8129909 8182765
* @bug 8004834 8007610 8129909 8182765 8247815
* @summary Add doclint support into javadoc
* @modules jdk.compiler/com.sun.tools.javac.main
*/
@ -178,7 +178,7 @@ public class DocLintTest {
Main.Result.OK,
EnumSet.of(Message.DL_WRN12));
test(List.of(htmlVersion, rawDiags, "-Xdoclint:syntax"),
test(List.of(htmlVersion, rawDiags, "-Xdoclint:missing"),
Main.Result.OK,
EnumSet.of(Message.DL_WRN12));
@ -186,7 +186,7 @@ public class DocLintTest {
Main.Result.ERROR,
EnumSet.of(Message.DL_ERR6, Message.DL_ERR9, Message.DL_WRN12));
test(List.of(htmlVersion, rawDiags, "-Xdoclint:syntax", "-private"),
test(List.of(htmlVersion, rawDiags, "-Xdoclint:missing,syntax", "-private"),
Main.Result.ERROR,
EnumSet.of(Message.DL_ERR6, Message.DL_WRN12));

@ -23,7 +23,7 @@
/**
* @test
* @bug 8241950
* @bug 8241950 8247932
* @summary Check the UI behavior of indentation
* @library /tools/lib
* @modules
@ -70,6 +70,11 @@ public class IndentUITest extends UITesting {
waitOutput(out, "^void test2\\(\\) \\{\n" +
CONTINUATION_PROMPT + " System.err.println\\(1\\);\n" +
CONTINUATION_PROMPT + "\\}");
inputSink.write(INTERRUPT);
waitOutput(out, "\u001B\\[\\?2004h" + PROMPT);
inputSink.write("\"\"\"\n");
waitOutput(out, "^\"\"\"\n" +
CONTINUATION_PROMPT);
});
}

@ -132,7 +132,7 @@ public class ToolSimpleTest extends ReplToolTesting {
+ "| Caused by: java.io.IOException: bar\n"
+ "| at n (#2:1)\n"
+ "| ...\n"
+ "| Caused by: java.lang.NullPointerException\n"
+ "| Caused by: java.lang.NullPointerException: Cannot invoke \"String.toString()\" because \"null\" is null\n"
+ "| at p (#1:1)\n"
+ "| ..."),
(a) -> assertCommand(a, "/drop p",

@ -1,11 +1,11 @@
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @bug 8004832 8247815
* @summary Add new doclint package
* @modules jdk.compiler/com.sun.tools.doclint
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-syntax EmptyAuthorTest.java
* @run main DocLintTester -Xmsgs:syntax -ref EmptyAuthorTest.out EmptyAuthorTest.java
* @run main DocLintTester -Xmsgs:-missing EmptyAuthorTest.java
* @run main DocLintTester -Xmsgs:missing -ref EmptyAuthorTest.out EmptyAuthorTest.java
*/
/** @author */

@ -1,15 +1,15 @@
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @bug 8004832 8247815
* @summary Add new doclint package
* @modules jdk.compiler/com.sun.tools.doclint
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-syntax EmptyExceptionTest.java
* @run main DocLintTester -Xmsgs:syntax -ref EmptyExceptionTest.out EmptyExceptionTest.java
* @run main DocLintTester -Xmsgs:-missing EmptyExceptionTest.java
* @run main DocLintTester -Xmsgs:missing -ref EmptyExceptionTest.out EmptyExceptionTest.java
*/
/** . */
public class EmptyExceptionTest {
/** @exception NullPointerException */
int emptyException() throws NullPointerException { }
void emptyException() throws NullPointerException { }
}

@ -1,15 +1,15 @@
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @bug 8004832 8247815
* @summary Add new doclint package
* @modules jdk.compiler/com.sun.tools.doclint
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-syntax EmptyParamTest.java
* @run main DocLintTester -Xmsgs:syntax -ref EmptyParamTest.out EmptyParamTest.java
* @run main DocLintTester -Xmsgs:-missing EmptyParamTest.java
* @run main DocLintTester -Xmsgs:missing -ref EmptyParamTest.out EmptyParamTest.java
*/
/** . */
public class EmptyParamTest {
/** @param i */
int emptyParam(int i) { }
void emptyParam(int i) { }
}

@ -1,15 +1,15 @@
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @bug 8004832 8247815
* @summary Add new doclint package
* @modules jdk.compiler/com.sun.tools.doclint
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-syntax EmptyReturnTest.java
* @run main DocLintTester -Xmsgs:syntax -ref EmptyReturnTest.out EmptyReturnTest.java
* @run main DocLintTester -Xmsgs:-missing EmptyReturnTest.java
* @run main DocLintTester -Xmsgs:missing -ref EmptyReturnTest.out EmptyReturnTest.java
*/
/** . */
public class EmptyReturnTest {
/** @return */
int emptyReturn() { }
int emptyReturn() { return 0; }
}

@ -1,11 +1,11 @@
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @bug 8004832 8247815
* @summary Add new doclint package
* @modules jdk.compiler/com.sun.tools.doclint
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-syntax EmptySerialDataTest.java
* @run main DocLintTester -Xmsgs:syntax -ref EmptySerialDataTest.out EmptySerialDataTest.java
* @run main DocLintTester -Xmsgs:-missing EmptySerialDataTest.java
* @run main DocLintTester -Xmsgs:missing -ref EmptySerialDataTest.out EmptySerialDataTest.java
*/
import java.io.ObjectOutputStream;
@ -13,6 +13,10 @@ import java.io.Serializable;
/** . */
public class EmptySerialDataTest implements Serializable {
/** @serialData */
/**
* .
* @serialData
* @param s .
*/
private void writeObject(ObjectOutputStream s) { }
}

@ -1,5 +1,5 @@
EmptySerialDataTest.java:16: warning: no description for @serialData
/** @serialData */
^
EmptySerialDataTest.java:18: warning: no description for @serialData
* @serialData
^
1 warning

@ -1,11 +1,11 @@
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @bug 8004832 8247815
* @summary Add new doclint package
* @modules jdk.compiler/com.sun.tools.doclint
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-syntax EmptySerialFieldTest.java
* @run main DocLintTester -Xmsgs:syntax -ref EmptySerialFieldTest.out EmptySerialFieldTest.java
* @run main DocLintTester -Xmsgs:-missing EmptySerialFieldTest.java
* @run main DocLintTester -Xmsgs:missing -ref EmptySerialFieldTest.out EmptySerialFieldTest.java
*/
import java.io.ObjectStreamField;

@ -1,15 +1,15 @@
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @bug 8004832 8247815
* @summary Add new doclint package
* @modules jdk.compiler/com.sun.tools.doclint
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-syntax EmptySinceTest.java
* @run main DocLintTester -Xmsgs:syntax -ref EmptySinceTest.out EmptySinceTest.java
* @run main DocLintTester -Xmsgs:-missing EmptySinceTest.java
* @run main DocLintTester -Xmsgs:missing -ref EmptySinceTest.out EmptySinceTest.java
*/
/** . */
public class EmptySinceTest {
/** @since */
int emptySince() { }
void emptySince() { }
}

@ -1,15 +1,15 @@
/*
* @test /nodynamiccopyright/
* @bug 8004832
* @bug 8004832 8247815
* @summary Add new doclint package
* @modules jdk.compiler/com.sun.tools.doclint
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-syntax EmptyVersionTest.java
* @run main DocLintTester -Xmsgs:syntax -ref EmptyVersionTest.out EmptyVersionTest.java
* @run main DocLintTester -Xmsgs:-missing EmptyVersionTest.java
* @run main DocLintTester -Xmsgs:missing -ref EmptyVersionTest.out EmptyVersionTest.java
*/
/** . */
public class EmptyVersionTest {
/** @version */
int missingVersion() { }
void missingVersion() { }
}

@ -1,8 +1,8 @@
/*
* @test /nodynamiccopyright/
* @bug 8198552
* @bug 8198552 8247815
* @summary Check that -Xdoclint: option can be specified multiple times
* @compile/fail/ref=MultipleDocLintOptionsTest.out -Xdoclint:html -Xdoclint:syntax -XDrawDiagnostics MultipleDocLintOptionsTest.java
* @compile/fail/ref=MultipleDocLintOptionsTest.out -Xdoclint:html -Xdoclint:missing -XDrawDiagnostics MultipleDocLintOptionsTest.java
*/
/** <html> */

@ -135,7 +135,7 @@ public class DocLintTest {
Main.Result.OK,
EnumSet.of(Message.DL_WRN12));
test(Arrays.asList(rawDiags, "-Xdoclint:syntax"),
test(Arrays.asList(rawDiags, "-Xdoclint:syntax,missing"),
Main.Result.ERROR,
EnumSet.of(Message.DL_ERR6, Message.DL_WRN12));

@ -23,45 +23,58 @@
/*
* @test
* @bug 8234729
* @bug 8234729 8242214
* @summary Javac should eagerly change code generation for method references to avert IllegalAccessError in future.
* @compile ProtectedInaccessibleMethodRefTest2.java
* @run main ProtectedInaccessibleMethodRefTest2
*/
import pack.I;
import pack.J;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.function.Function;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.BiFunction;
public final class ProtectedInaccessibleMethodRefTest2 extends I {
public static void main(String... args) {
ProtectedInaccessibleMethodRefTest2 m = new ProtectedInaccessibleMethodRefTest2();
m.test(Paths.get("test"));
// Verify that the method reference has been folded into a lambda.
boolean lambdaFound = false;
// Verify that the method references have been folded into lambdas:
Set<String> methodNames = new HashSet<>();
for (Method meth : ProtectedInaccessibleMethodRefTest2.class.getDeclaredMethods()) {
if (meth.getName().equals("lambda$test$0")) {
lambdaFound = true;
break;
}
methodNames.add(meth.getName());
}
if (!lambdaFound) {
List<String> expectedMethods =
Arrays.asList("lambda$test$0", "lambda$test$1", "lambda$test$2");
if (!methodNames.containsAll(expectedMethods)) {
throw new AssertionError("Did not find evidence of new code generation");
}
}
void test(Path outputDir) {
Sub c = new Sub(this::readFile);
c.check(outputDir);
Sub c1 = new Sub(this::readFile);
c1.check(outputDir);
Sub c2 = new Sub(ProtectedInaccessibleMethodRefTest2::readFile, this);
c2.check(outputDir);
Sub c3 = new Sub(ProtectedInaccessibleMethodRefTest2::readFile2);
c3.check(outputDir);
}
public class Sub extends J {
Sub(Function<Path,String> fileReader) {
super(fileReader);
}
Sub(BiFunction<ProtectedInaccessibleMethodRefTest2, Path,String> fileReader,
ProtectedInaccessibleMethodRefTest2 instance) {
super(p -> fileReader.apply(instance, p));
}
}
}

@ -29,4 +29,8 @@ public class I {
protected String readFile(Path file) {
return file.toString();
}
protected static String readFile2(Path file) {
return file.toString();
}
}