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

View file

@ -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.

View file

@ -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
*/

View file

@ -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>

View file

@ -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) {

View file

@ -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:

View file

@ -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 {

View file

@ -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

View file

@ -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}
*

View file

@ -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
{