aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Jesper Wilhelmsson <jesper.wilhelmsson@oracle.com> 2021-07-14 23:34:17 +0200
committerGravatar Jesper Wilhelmsson <jesper.wilhelmsson@oracle.com> 2021-07-14 23:34:17 +0200
commit532619b01cea5f778c66ef156b3cdc38a1e58e91 (patch)
tree2f878cb8728fc8a3134c6bdddc1c504e208ae85c
parenta033866d786507db69ab75643684e617fd1f4ba2 (diff)
parent7b4d84c65487593cdbf841f7f2d359192476db99 (diff)
downloadjdk-pr/4786.tar.gz
jdk-pr/4786.zip
Mergepr/4786
-rw-r--r--make/CreateJmods.gmk6
-rw-r--r--src/hotspot/share/logging/logAsyncWriter.cpp25
-rw-r--r--src/hotspot/share/logging/logAsyncWriter.hpp9
-rw-r--r--src/hotspot/share/prims/jvmtiEnv.cpp7
-rw-r--r--src/java.base/share/classes/java/util/SplittableRandom.java66
-rw-r--r--src/java.base/share/classes/java/util/random/RandomGenerator.java79
-rw-r--r--src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java2
-rw-r--r--src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java10
-rw-r--r--src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java12
-rw-r--r--src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java3
-rw-r--r--src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java3
-rw-r--r--src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java15
-rw-r--r--src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkFactory.java16
-rw-r--r--src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkInfo.java8
-rw-r--r--test/langtools/jdk/javadoc/doclet/testGenericTypeLink/TestGenericTypeLink.java36
-rw-r--r--test/langtools/jdk/javadoc/doclet/testGenericTypeLink/pkg1/A.java12
-rw-r--r--test/langtools/jdk/javadoc/doclet/testGenericTypeLink/pkg1/C.java33
-rw-r--r--test/langtools/jdk/javadoc/doclet/testMethodSignature/TestMethodSignature.java29
-rw-r--r--test/langtools/jdk/javadoc/doclet/testMethodSignature/pkg/C.java31
19 files changed, 314 insertions, 88 deletions
diff --git a/make/CreateJmods.gmk b/make/CreateJmods.gmk
index 01ce2cf48ea..6edc69397a5 100644
--- a/make/CreateJmods.gmk
+++ b/make/CreateJmods.gmk
@@ -213,12 +213,12 @@ endif
ifeq ($(call isTargetOs, windows), true)
ifeq ($(SHIP_DEBUG_SYMBOLS), )
- JMOD_FLAGS += --exclude '**{_the.*,_*.marker,*.diz,*.pdb,*.map}'
+ JMOD_FLAGS += --exclude '**{_the.*,_*.marker*,*.diz,*.pdb,*.map}'
else
- JMOD_FLAGS += --exclude '**{_the.*,_*.marker,*.diz,*.map}'
+ JMOD_FLAGS += --exclude '**{_the.*,_*.marker*,*.diz,*.map}'
endif
else
- JMOD_FLAGS += --exclude '**{_the.*,_*.marker,*.diz,*.debuginfo,*.dSYM/**,*.dSYM}'
+ JMOD_FLAGS += --exclude '**{_the.*,_*.marker*,*.diz,*.debuginfo,*.dSYM/**,*.dSYM}'
endif
# Create jmods in the support dir and then move them into place to keep the
diff --git a/src/hotspot/share/logging/logAsyncWriter.cpp b/src/hotspot/share/logging/logAsyncWriter.cpp
index 9bebd82c76e..40e516606aa 100644
--- a/src/hotspot/share/logging/logAsyncWriter.cpp
+++ b/src/hotspot/share/logging/logAsyncWriter.cpp
@@ -27,16 +27,17 @@
#include "logging/logFileOutput.hpp"
#include "logging/logHandle.hpp"
#include "runtime/atomic.hpp"
+#include "runtime/os.inline.hpp"
class AsyncLogWriter::AsyncLogLocker : public StackObj {
public:
AsyncLogLocker() {
assert(_instance != nullptr, "AsyncLogWriter::_lock is unavailable");
- _instance->_lock.wait();
+ _instance->_lock.lock();
}
~AsyncLogLocker() {
- _instance->_lock.signal();
+ _instance->_lock.unlock();
}
};
@@ -51,7 +52,8 @@ void AsyncLogWriter::enqueue_locked(const AsyncLogMessage& msg) {
}
_buffer.push_back(msg);
- _sem.signal();
+ _data_available = true;
+ _lock.notify();
}
void AsyncLogWriter::enqueue(LogFileOutput& output, const LogDecorations& decorations, const char* msg) {
@@ -75,7 +77,7 @@ void AsyncLogWriter::enqueue(LogFileOutput& output, LogMessageBuffer::Iterator m
}
AsyncLogWriter::AsyncLogWriter()
- : _lock(1), _sem(0), _flush_sem(0),
+ : _flush_sem(0), _lock(), _data_available(false),
_initialized(false),
_stats() {
if (os::create_thread(this, os::asynclog_thread)) {
@@ -125,6 +127,7 @@ void AsyncLogWriter::write() {
// append meta-messages of dropped counters
AsyncLogMapIterator dropped_counters_iter(logs);
_stats.iterate(&dropped_counters_iter);
+ _data_available = false;
}
LinkedListIterator<AsyncLogMessage> it(logs.head());
@@ -152,9 +155,14 @@ void AsyncLogWriter::write() {
void AsyncLogWriter::run() {
while (true) {
- // The value of a semphore cannot be negative. Therefore, the current thread falls asleep
- // when its value is zero. It will be waken up when new messages are enqueued.
- _sem.wait();
+ {
+ AsyncLogLocker locker;
+
+ while (!_data_available) {
+ _lock.wait(0/* no timeout */);
+ }
+ }
+
write();
}
}
@@ -198,7 +206,8 @@ void AsyncLogWriter::flush() {
// Push directly in-case we are at logical max capacity, as this must not get dropped.
_instance->_buffer.push_back(token);
- _instance->_sem.signal();
+ _instance->_data_available = true;
+ _instance->_lock.notify();
}
_instance->_flush_sem.wait();
diff --git a/src/hotspot/share/logging/logAsyncWriter.hpp b/src/hotspot/share/logging/logAsyncWriter.hpp
index 5a3174b9e79..5a3fd464908 100644
--- a/src/hotspot/share/logging/logAsyncWriter.hpp
+++ b/src/hotspot/share/logging/logAsyncWriter.hpp
@@ -141,13 +141,10 @@ class AsyncLogWriter : public NonJavaThread {
class AsyncLogLocker;
static AsyncLogWriter* _instance;
- // _lock(1) denotes a critional region.
- Semaphore _lock;
- // _sem is a semaphore whose value denotes how many messages have been enqueued.
- // It decreases in AsyncLogWriter::run()
- Semaphore _sem;
Semaphore _flush_sem;
-
+ // Can't use a Monitor here as we need a low-level API that can be used without Thread::current().
+ os::PlatformMonitor _lock;
+ bool _data_available;
volatile bool _initialized;
AsyncLogMap _stats; // statistics for dropped messages
AsyncLogBuffer _buffer;
diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp
index 5e3712ce6f9..f04dc7dd27c 100644
--- a/src/hotspot/share/prims/jvmtiEnv.cpp
+++ b/src/hotspot/share/prims/jvmtiEnv.cpp
@@ -3135,7 +3135,10 @@ JvmtiEnv::RawMonitorEnter(JvmtiRawMonitor * rmonitor) {
// in thread.cpp.
JvmtiPendingMonitors::enter(rmonitor);
} else {
- rmonitor->raw_enter(Thread::current());
+ Thread* thread = Thread::current();
+ // 8266889: raw_enter changes Java thread state, needs WXWrite
+ MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread));
+ rmonitor->raw_enter(thread);
}
return JVMTI_ERROR_NONE;
} /* end RawMonitorEnter */
@@ -3167,6 +3170,8 @@ JvmtiEnv::RawMonitorExit(JvmtiRawMonitor * rmonitor) {
jvmtiError
JvmtiEnv::RawMonitorWait(JvmtiRawMonitor * rmonitor, jlong millis) {
Thread* thread = Thread::current();
+ // 8266889: raw_wait changes Java thread state, needs WXWrite
+ MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread));
int r = rmonitor->raw_wait(millis, thread);
switch (r) {
diff --git a/src/java.base/share/classes/java/util/SplittableRandom.java b/src/java.base/share/classes/java/util/SplittableRandom.java
index 77bfa17593a..f3dd55a161a 100644
--- a/src/java.base/share/classes/java/util/SplittableRandom.java
+++ b/src/java.base/share/classes/java/util/SplittableRandom.java
@@ -26,6 +26,8 @@ package java.util;
import java.math.BigInteger;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator;
+import java.util.random.RandomGenerator.SplittableGenerator;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
@@ -86,13 +88,12 @@ import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
* @author Doug Lea
* @since 1.8
*/
-@SuppressWarnings("exports")
@RandomGeneratorProperties(
name = "SplittableRandom",
i = 64, j = 0, k = 0,
equidistribution = 1
)
-public final class SplittableRandom extends AbstractSplittableGenerator {
+public final class SplittableRandom implements RandomGenerator, SplittableGenerator {
/*
* Implementation Overview.
@@ -182,6 +183,7 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
private SplittableRandom(long seed, long gamma) {
this.seed = seed;
this.gamma = gamma;
+ this.proxy = new AbstractSplittableGeneratorProxy();
}
/**
@@ -217,6 +219,31 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
}
/**
+ * Proxy class to non-public RandomSupportAbstractSplittableGenerator.
+ */
+ private class AbstractSplittableGeneratorProxy extends AbstractSplittableGenerator {
+ @Override
+ public int nextInt() {
+ return SplittableRandom.this.nextInt();
+ }
+
+ @Override
+ public long nextLong() {
+ return SplittableRandom.this.nextLong();
+ }
+
+ @Override
+ public java.util.SplittableRandom split(SplittableGenerator source) {
+ return new SplittableRandom(source.nextLong(), mixGamma(source.nextLong()));
+ }
+ }
+
+ /**
+ * Proxy object to non-public RandomSupportAbstractSplittableGenerator.
+ */
+ private AbstractSplittableGeneratorProxy proxy;
+
+ /**
* Adds gamma to seed.
*/
private long nextSeed() {
@@ -251,6 +278,7 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
long s = defaultGen.getAndAdd(2 * GOLDEN_GAMMA);
this.seed = mix64(s);
this.gamma = mixGamma(s + GOLDEN_GAMMA);
+ this.proxy = new AbstractSplittableGeneratorProxy();
}
/**
@@ -297,7 +325,7 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
*/
@Override
public void nextBytes(byte[] bytes) {
- super.nextBytes(bytes);
+ proxy.nextBytes(bytes);
}
/**
@@ -307,7 +335,7 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
*/
@Override
public Stream<SplittableGenerator> splits() {
- return super.splits();
+ return proxy.splits();
}
/**
@@ -318,7 +346,7 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
*/
@Override
public Stream<SplittableGenerator> splits(long streamSize) {
- return super.splits(streamSize, this);
+ return proxy.splits(streamSize, this);
}
/**
@@ -329,7 +357,7 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
*/
@Override
public Stream<SplittableGenerator> splits(SplittableGenerator source) {
- return super.splits(Long.MAX_VALUE, source);
+ return proxy.splits(Long.MAX_VALUE, source);
}
/**
@@ -341,7 +369,7 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
*/
@Override
public Stream<SplittableGenerator> splits(long streamSize, SplittableGenerator source) {
- return super.splits(streamSize, source);
+ return proxy.splits(streamSize, source);
}
/**
@@ -356,7 +384,7 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
*/
@Override
public IntStream ints(long streamSize) {
- return super.ints(streamSize);
+ return proxy.ints(streamSize);
}
/**
@@ -370,7 +398,7 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
*/
@Override
public IntStream ints() {
- return super.ints();
+ return proxy.ints();
}
/**
@@ -390,7 +418,7 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
*/
@Override
public IntStream ints(long streamSize, int randomNumberOrigin, int randomNumberBound) {
- return super.ints(streamSize, randomNumberOrigin, randomNumberBound);
+ return proxy.ints(streamSize, randomNumberOrigin, randomNumberBound);
}
/**
@@ -410,7 +438,7 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
*/
@Override
public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
- return super.ints(randomNumberOrigin, randomNumberBound);
+ return proxy.ints(randomNumberOrigin, randomNumberBound);
}
/**
@@ -425,7 +453,7 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
*/
@Override
public LongStream longs(long streamSize) {
- return super.longs(streamSize);
+ return proxy.longs(streamSize);
}
/**
@@ -439,7 +467,7 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
*/
@Override
public LongStream longs() {
- return super.longs();
+ return proxy.longs();
}
/**
@@ -459,7 +487,7 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
*/
@Override
public LongStream longs(long streamSize, long randomNumberOrigin, long randomNumberBound) {
- return super.longs(streamSize, randomNumberOrigin, randomNumberBound);
+ return proxy.longs(streamSize, randomNumberOrigin, randomNumberBound);
}
/**
@@ -479,7 +507,7 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
*/
@Override
public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
- return super.longs(randomNumberOrigin, randomNumberBound);
+ return proxy.longs(randomNumberOrigin, randomNumberBound);
}
/**
@@ -494,7 +522,7 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
*/
@Override
public DoubleStream doubles(long streamSize) {
- return super.doubles(streamSize);
+ return proxy.doubles(streamSize);
}
/**
@@ -509,7 +537,7 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
*/
@Override
public DoubleStream doubles() {
- return super.doubles();
+ return proxy.doubles();
}
/**
@@ -529,7 +557,7 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
*/
@Override
public DoubleStream doubles(long streamSize, double randomNumberOrigin, double randomNumberBound) {
- return super.doubles(streamSize, randomNumberOrigin, randomNumberBound);
+ return proxy.doubles(streamSize, randomNumberOrigin, randomNumberBound);
}
/**
@@ -549,6 +577,6 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
*/
@Override
public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
- return super.doubles(randomNumberOrigin, randomNumberBound);
+ return proxy.doubles(randomNumberOrigin, randomNumberBound);
}
}
diff --git a/src/java.base/share/classes/java/util/random/RandomGenerator.java b/src/java.base/share/classes/java/util/random/RandomGenerator.java
index 0080a897892..9feff713192 100644
--- a/src/java.base/share/classes/java/util/random/RandomGenerator.java
+++ b/src/java.base/share/classes/java/util/random/RandomGenerator.java
@@ -516,9 +516,10 @@ public interface RandomGenerator {
* @throws IllegalArgumentException if {@code bound} is not
* both positive and finite
*
- * @implSpec The default implementation simply calls
- * {@link RandomSupport#checkBound checkBound}(bound) and then
- * {@link RandomSupport#boundedNextFloat boundedNextFloat}(this, bound).
+ * @implSpec The default implementation checks that {@code bound} is a
+ * positive finite float. Then invokes {@code nextFloat()}, scaling
+ * the result so that the final result lies between {@code 0.0f} (inclusive)
+ * and {@code bound} (exclusive).
*/
default float nextFloat(float bound) {
RandomSupport.checkBound(bound);
@@ -540,9 +541,11 @@ public interface RandomGenerator {
* or {@code bound} is not finite, or {@code origin}
* is greater than or equal to {@code bound}
*
- * @implSpec The default implementation simply calls
- * {@link RandomSupport#checkBound checkBound}(bound) and then
- * {@link RandomSupport#boundedNextFloat boundedNextFloat}(this, bound).
+ * @implSpec The default implementation checks that {@code origin} and
+ * {@code bound} are positive finite floats. Then invokes
+ * {@code nextFloat()}, scaling and translating the result so that the final
+ * result lies between {@code origin} (inclusive) and {@code bound}
+ * (exclusive).
*/
default float nextFloat(float origin, float bound) {
RandomSupport.checkRange(origin, bound);
@@ -577,9 +580,10 @@ public interface RandomGenerator {
* @throws IllegalArgumentException if {@code bound} is not
* both positive and finite
*
- * @implSpec The default implementation simply calls
- * {@link RandomSupport#checkBound checkBound}(bound) and then
- * {@link RandomSupport#boundedNextDouble boundedNextDouble}(this, bound).
+ * @implSpec The default implementation checks that {@code bound} is a
+ * positive finite double. Then invokes {@code nextDouble()}, scaling
+ * the result so that the final result lies between {@code 0.0} (inclusive)
+ * and {@code bound} (exclusive).
*/
default double nextDouble(double bound) {
RandomSupport.checkBound(bound);
@@ -601,9 +605,11 @@ public interface RandomGenerator {
* or {@code bound} is not finite, or {@code origin}
* is greater than or equal to {@code bound}
*
- * @implSpec The default implementation simply calls
- * {@link RandomSupport#checkBound checkBound}(bound) and then
- * {@link RandomSupport#boundedNextDouble boundedNextDouble}(this, bound).
+ * @implSpec The default implementation checks that {@code origin} and
+ * {@code bound} are positive finite doubles. Then calls
+ * {@code nextDouble()}, scaling and translating the result so that the final
+ * result lies between {@code origin} (inclusive) and {@code bound}
+ * (exclusive).
*/
default double nextDouble(double origin, double bound) {
RandomSupport.checkRange(origin, bound);
@@ -627,16 +633,20 @@ public interface RandomGenerator {
* Returns a pseudorandomly chosen {@code int} value between zero
* (inclusive) and the specified bound (exclusive).
*
- * @param bound the upper bound (exclusive) for the returned value. Must be positive.
+ * @param bound the upper bound (exclusive) for the returned value.
+ * Must be positive.
*
* @return a pseudorandomly chosen {@code int} value between
* zero (inclusive) and the bound (exclusive)
*
* @throws IllegalArgumentException if {@code bound} is not positive
*
- * @implSpec The default implementation simply calls
- * {@link RandomSupport#checkBound checkBound}(bound) and then
- * {@link RandomSupport#boundedNextInt boundedNextInt}(this, bound).
+ * @implSpec The default implementation checks that {@code bound} is a
+ * positive {@code int}. Then invokes {@code nextInt()}, limiting the result
+ * to be greater than or equal zero and less than {@code bound}. If {@code bound}
+ * is a power of two then limiting is a simple masking operation. Otherwise,
+ * the result is re-calculated by invoking {@code nextInt()} until the
+ * result is greater than or equal zero and less than {@code bound}.
*/
default int nextInt(int bound) {
RandomSupport.checkBound(bound);
@@ -657,9 +667,13 @@ public interface RandomGenerator {
* @throws IllegalArgumentException if {@code origin} is greater than
* or equal to {@code bound}
*
- * @implSpec The default implementation simply calls
- * {@link RandomSupport#checkBound(long) checkBound}(bound) and then
- * {@link RandomSupport#boundedNextInt(RandomGenerator, int) boundedNextInt}(this, bound).
+ * @implSpec The default implementation checks that {@code origin} and
+ * {@code bound} are positive {@code ints}. Then invokes {@code nextInt()},
+ * limiting the result to be greater that or equal {@code origin} and less
+ * than {@code bound}. If {@code bound} is a power of two then limiting is a
+ * simple masking operation. Otherwise, the result is re-calculated by
+ * invoking {@code nextInt()} until the result is greater than or equal
+ * {@code origin} and less than {@code bound}.
*/
default int nextInt(int origin, int bound) {
RandomSupport.checkRange(origin, bound);
@@ -678,16 +692,21 @@ public interface RandomGenerator {
* Returns a pseudorandomly chosen {@code long} value between zero
* (inclusive) and the specified bound (exclusive).
*
- * @param bound the upper bound (exclusive) for the returned value. Must be positive.
+ * @param bound the upper bound (exclusive) for the returned value.
+ * Must be positive.
*
* @return a pseudorandomly chosen {@code long} value between
* zero (inclusive) and the bound (exclusive)
*
* @throws IllegalArgumentException if {@code bound} is not positive
*
- * @implSpec The default implementation simply calls
- * {@link RandomSupport#checkBound checkBound}(bound) and then
- * {@link RandomSupport#boundedNextLong boundedNextLong}(this, bound).
+ * @implSpec The default implementation checks that {@code bound} is a
+ * positive {@code long}. Then invokes {@code nextLong()}, limiting the
+ * result to be greater than or equal zero and less than {@code bound}. If
+ * {@code bound} is a power of two then limiting is a simple masking
+ * operation. Otherwise, the result is re-calculated by invoking
+ * {@code nextLong()} until the result is greater than or equal zero and
+ * less than {@code bound}.
*/
default long nextLong(long bound) {
RandomSupport.checkBound(bound);
@@ -708,9 +727,13 @@ public interface RandomGenerator {
* @throws IllegalArgumentException if {@code origin} is greater than
* or equal to {@code bound}
*
- * @implSpec The default implementation simply calls
- * {@link RandomSupport#checkBound checkBound}(bound) and then
- * {@link RandomSupport#boundedNextLong boundedNextLong}(this, bound).
+ * @implSpec The default implementation checks that {@code origin} and
+ * {@code bound} are positive {@code longs}. Then invokes {@code nextLong()},
+ * limiting the result to be greater than or equal {@code origin} and less
+ * than {@code bound}. If {@code bound} is a power of two then limiting is a
+ * simple masking operation. Otherwise, the result is re-calculated by
+ * invoking {@code nextLong()} until the result is greater than or equal
+ * {@code origin} and less than {@code bound}.
*/
default long nextLong(long origin, long bound) {
RandomSupport.checkRange(origin, bound);
@@ -892,10 +915,6 @@ public interface RandomGenerator {
* Returns an instance of {@link SplittableGenerator} that utilizes the
* {@code name} <a href="package-summary.html#algorithms">algorithm</a>.
*
- * @implNote Availability is determined by RandomGeneratorFactory using the
- * service provider API to locate implementations of the RandomGenerator
- * interface and filtering on the SplittableGenerator interface.
- *
* @param name Name of random number generator
* <a href="package-summary.html#algorithms">algorithm</a>
*
diff --git a/src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java b/src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java
index 2ed63f2455d..552d7b03d53 100644
--- a/src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java
+++ b/src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java
@@ -374,7 +374,7 @@ public final class RandomGeneratorFactory<T extends RandomGenerator> {
/**
* Returns a non-empty stream of available {@link RandomGeneratorFactory RandomGeneratorFactory(s)}.
*
- * RandomGenerators that are marked as deprecated or are not properly configured are not included in the result.
+ * RandomGenerators that are marked as deprecated are not included in the result.
*
* @implSpec Availability is determined by RandomGeneratorFactory using the service provider API
* to locate implementations of the RandomGenerator interface.
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java
index a3174e3e8be..39c15a82313 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java
@@ -133,13 +133,13 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite
/**
* Add the parameter for the executable member.
*
- * @param member the member to write parameter for.
* @param param the parameter that needs to be written.
+ * @param paramType the type of the parameter.
* @param isVarArg true if this is a link to var arg.
* @param tree the content tree to which the parameter information will be added.
*/
- protected void addParam(ExecutableElement member, VariableElement param, TypeMirror paramType,
- boolean isVarArg, Content tree) {
+ protected void addParam(VariableElement param, TypeMirror paramType, boolean isVarArg,
+ Content tree) {
Content link = writer.getLink(new HtmlLinkInfo(configuration, EXECUTABLE_MEMBER_PARAM,
paramType).varargs(isVarArg));
tree.add(link);
@@ -249,7 +249,7 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite
.add(" ");
}
}
- addParam(member, param, paramType,
+ addParam(param, paramType,
(paramstart == parameters.size() - 1) && member.isVarArgs(), paramTree);
break;
}
@@ -268,7 +268,7 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite
.add(" ");
}
}
- addParam(member, parameters.get(i), instMeth.getParameterTypes().get(i),
+ addParam(parameters.get(i), instMeth.getParameterTypes().get(i),
(i == parameters.size() - 1) && member.isVarArgs(),
paramTree);
}
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
index 0c8182e7a84..c95b735b709 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
@@ -1075,13 +1075,11 @@ public class HtmlDocletWriter {
} else if (refMemName == null) {
// Must be a class reference since refClass is not null and refMemName is null.
if (labelContent.isEmpty()) {
- if (!refClass.getTypeParameters().isEmpty() && seeText.contains("<")) {
- // If this is a generic type link try to use the TypeMirror representation.
- TypeMirror refType = ch.getReferencedType(see);
- if (refType != null) {
- return plainOrCode(isLinkPlain, getLink(
- new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.DEFAULT, refType)));
- }
+ TypeMirror referencedType = ch.getReferencedType(see);
+ if (utils.isGenericType(referencedType)) {
+ // This is a generic type link, use the TypeMirror representation.
+ return plainOrCode(isLinkPlain, getLink(
+ new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.DEFAULT, referencedType)));
}
labelContent = plainOrCode(isLinkPlain, Text.of(utils.getSimpleName(refClass)));
}
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java
index 805a7c3d519..ee09e99cea6 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java
@@ -107,8 +107,7 @@ public class HtmlLinkFactory extends LinkFactory {
if (utils.isIncluded(typeElement)) {
if (configuration.isGeneratedDoc(typeElement) && !utils.hasHiddenTag(typeElement)) {
DocPath filename = getPath(classLinkInfo);
- if (linkInfo.linkToSelf ||
- !(docPaths.forName(typeElement)).equals(m_writer.filename)) {
+ if (linkInfo.linkToSelf || typeElement != m_writer.getCurrentPageElement()) {
link.add(m_writer.links.createLink(
filename.fragment(classLinkInfo.where),
label,
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java
index 89635a3c585..65bcdce9181 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java
@@ -192,6 +192,9 @@ public class CommentHelper {
}
public TypeMirror getType(ReferenceTree rtree) {
+ // Workaround for JDK-8269706
+ if (path == null || dcTree == null || rtree == null)
+ return null;
DocTreePath docTreePath = DocTreePath.getPath(path, dcTree, rtree);
if (docTreePath != null) {
DocTrees doctrees = configuration.docEnv.getDocTrees();
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
index 4bcc5bf3acc..652f61caaa7 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
@@ -974,6 +974,21 @@ public class Utils {
}
/**
+ * Returns true if {@code type} or any of its enclosing types has non-empty type arguments.
+ * @param type the type
+ * @return {@code true} if type arguments were found
+ */
+ public boolean isGenericType(TypeMirror type) {
+ while (type instanceof DeclaredType dt) {
+ if (!dt.getTypeArguments().isEmpty()) {
+ return true;
+ }
+ type = dt.getEnclosingType();
+ }
+ return false;
+ }
+
+ /**
* TODO: FIXME: port to javax.lang.model
* Find a class within the context of this class. Search order: qualified name, in this class
* (inner), in this package, in the class imports, in the package imports. Return the
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkFactory.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkFactory.java
index cb1b16a4f88..c5e67990221 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkFactory.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkFactory.java
@@ -166,6 +166,16 @@ public abstract class LinkFactory {
@Override
public Content visitDeclared(DeclaredType type, LinkInfo linkInfo) {
+ TypeMirror enc = type.getEnclosingType();
+ if (enc instanceof DeclaredType dt && utils.isGenericType(dt)) {
+ // If an enclosing type has type parameters render them as separate links as
+ // otherwise this information is lost. On the other hand, plain enclosing types
+ // are not linked separately as they are easy to reach from the nested type.
+ setEnclosingTypeLinkInfo(linkInfo, dt);
+ visitDeclared(dt, linkInfo);
+ link.add(".");
+ setEnclosingTypeLinkInfo(linkInfo, type);
+ }
link.add(getTypeAnnotationLinks(linkInfo));
linkInfo.typeElement = utils.asTypeElement(type);
link.add(getClassLink(linkInfo));
@@ -195,6 +205,12 @@ public abstract class LinkFactory {
linkInfo.skipPreview = false;
}
+ private void setEnclosingTypeLinkInfo(LinkInfo linkinfo, DeclaredType enclosing) {
+ linkinfo.typeElement = null;
+ linkinfo.label = null;
+ linkinfo.type = enclosing;
+ }
+
/**
* Returns a link to the given class.
*
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkInfo.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkInfo.java
index 1907ad426d1..9094e04a087 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkInfo.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkInfo.java
@@ -27,10 +27,12 @@ package jdk.javadoc.internal.doclets.toolkit.util.links;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.util.Utils;
/**
* Encapsulates information about a link.
@@ -125,7 +127,11 @@ public abstract class LinkInfo {
return label;
} else if (isLinkable()) {
Content tlabel = newContent();
- tlabel.add(configuration.utils.getSimpleName(typeElement));
+ Utils utils = configuration.utils;
+ tlabel.add(type instanceof DeclaredType dt && utils.isGenericType(dt.getEnclosingType())
+ // If enclosing type is rendered as separate links only use own class name
+ ? typeElement.getSimpleName().toString()
+ : configuration.utils.getSimpleName(typeElement));
return tlabel;
} else {
Content tlabel = newContent();
diff --git a/test/langtools/jdk/javadoc/doclet/testGenericTypeLink/TestGenericTypeLink.java b/test/langtools/jdk/javadoc/doclet/testGenericTypeLink/TestGenericTypeLink.java
index cd289202c7a..fbfbb5f3978 100644
--- a/test/langtools/jdk/javadoc/doclet/testGenericTypeLink/TestGenericTypeLink.java
+++ b/test/langtools/jdk/javadoc/doclet/testGenericTypeLink/TestGenericTypeLink.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8177280 8262992
+ * @bug 8177280 8262992 8259499
* @summary see and link tag syntax should allow generic types
* @library ../../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool
@@ -118,6 +118,40 @@ public class TestGenericTypeLink extends JavadocTester {
</dd>
</dl>"""
);
+ checkOutput("pkg1/A.Inner.html", true,
+ """
+ <dl class="notes">
+ <dt>See Also:</dt>
+ <dd>
+ <ul class="see-list-long">
+ <li><code><a href="A.html" title="class in pkg1">A</a>&lt;<a href="http://exampl\
+ e.com/docs/api/java.base/java/lang/String.html" title="class or interface in jav\
+ a.lang" class="external-link">String</a>,<wbr><a href="http://example.com/docs/a\
+ pi/java.base/java/lang/RuntimeException.html" title="class or interface in java.\
+ lang" class="external-link">RuntimeException</a>&gt;.<a href="A.Inner.html" titl\
+ e="class in pkg1">Inner</a></code></li>
+ <li><code><a href="A.html" title="class in pkg1">A</a>&lt;<a href="A.html" title\
+ ="class in pkg1">A</a>&lt;<a href="http://example.com/docs/api/java.base/java/la\
+ ng/String.html" title="class or interface in java.lang" class="external-link">St\
+ ring</a>,<wbr><a href="http://example.com/docs/api/java.base/java/lang/RuntimeEx\
+ ception.html" title="class or interface in java.lang" class="external-link">Runt\
+ imeException</a>&gt;.<a href="A.Inner.html" title="class in pkg1">Inner</a>,<wbr\
+ ><a href="A.SomeException.html" title="class in pkg1">A.SomeException</a>&gt;</c\
+ ode></li>
+ </ul>
+ </dd>
+ </dl>""");
+
+ checkOutput("pkg1/C.html", true,
+ """
+ Description copied from class:&nbsp;<code><a href="A.html#overriddenMethod()">A<\
+ /a></code></span></div>
+ <div class="block">Here's a generic link: <code><a href="A.html" title="class in\
+ pkg1">A</a>&lt;<a href="http://example.com/docs/api/java.base/java/lang/Object.\
+ html" title="class or interface in java.lang" class="external-link">Object</a>,<\
+ wbr><a href="http://example.com/docs/api/java.base/java/lang/RuntimeException.ht\
+ ml" title="class or interface in java.lang" class="external-link">RuntimeExcepti\
+ on</a>&gt;.<a href="A.Inner.html" title="class in pkg1">Inner</a>""");
}
/**
diff --git a/test/langtools/jdk/javadoc/doclet/testGenericTypeLink/pkg1/A.java b/test/langtools/jdk/javadoc/doclet/testGenericTypeLink/pkg1/A.java
index e665cab02e5..bae55f24dbd 100644
--- a/test/langtools/jdk/javadoc/doclet/testGenericTypeLink/pkg1/A.java
+++ b/test/langtools/jdk/javadoc/doclet/testGenericTypeLink/pkg1/A.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -60,6 +60,16 @@ public class A<T, E extends Exception> {
*/
public void otherMethod(Map<String, ?> list, double d) {}
+ /**
+ * Here's a generic link: {@link A<Object, RuntimeException>.Inner}
+ */
+ public void overriddenMethod() {}
+
+ /**
+ * @see A<String, java.lang.RuntimeException>.Inner
+ * @see A<A<String, java.lang.RuntimeException>.Inner, A.SomeException>
+ */
+ class Inner {}
}
diff --git a/test/langtools/jdk/javadoc/doclet/testGenericTypeLink/pkg1/C.java b/test/langtools/jdk/javadoc/doclet/testGenericTypeLink/pkg1/C.java
new file mode 100644
index 00000000000..400eaa0970b
--- /dev/null
+++ b/test/langtools/jdk/javadoc/doclet/testGenericTypeLink/pkg1/C.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 pkg1;
+
+import java.util.Map;
+
+public class C<T, E extends Exception> extends A {
+
+ @Override
+ public void overriddenMethod() {}
+
+}
diff --git a/test/langtools/jdk/javadoc/doclet/testMethodSignature/TestMethodSignature.java b/test/langtools/jdk/javadoc/doclet/testMethodSignature/TestMethodSignature.java
index 77acf2b168a..afb2e93a01f 100644
--- a/test/langtools/jdk/javadoc/doclet/testMethodSignature/TestMethodSignature.java
+++ b/test/langtools/jdk/javadoc/doclet/testMethodSignature/TestMethodSignature.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8214126 8241470
+ * @bug 8214126 8241470 8259499
* @summary Method signatures not formatted correctly in browser
* @library ../../lib/
* @modules jdk.javadoc/jdk.javadoc.internal.tool
@@ -123,7 +123,32 @@ public class TestMethodSignature extends JavadocTester {
throws <span class="exc\
eptions">java.lang.IllegalArgumentException,
java.lang.IllegalStateException</span></div>
- <div class="block">Generic method with eight type args and annotation.</div>""");
+ <div class="block">Generic method with eight type args and annotation.</div>""",
+ """
+ <div class="member-signature"><span class="modifiers">public</span>&nbsp;<span c\
+ lass="return-type"><a href="C.Generic.html" title="class in pkg">C.Generic</a>&l\
+ t;java.lang.Integer&gt;.<a href="C.Generic.Inner.html" title="class in pkg">Inne\
+ r</a></span>&nbsp;<span class="element-name">nestedGeneric1</span><wbr><span cla\
+ ss="parameters">(<a href="C.Generic.html" title="class in pkg">C.Generic</a>&lt;\
+ java.lang.Integer&gt;.<a href="C.Generic.Inner.html" title="class in pkg">Inner<\
+ /a>&nbsp;i,
+ <a href="C.Generic.html" title="class in pkg">C.Generic</a>&lt;<a href="C.html"\
+ title="class in pkg">C</a>&gt;.<a href="C.Generic.Inner.html" title="class in p\
+ kg">Inner</a>&nbsp;j)</span></div>""",
+ """
+ <div class="member-signature"><span class="modifiers">public</span>&nbsp;<span c\
+ lass="return-type"><a href="C.Generic.html" title="class in pkg">C.Generic</a>&l\
+ t;<a href="C.F0.html" title="interface in pkg">C.F0</a>&lt;<a href="C.html" titl\
+ e="class in pkg">C</a>&gt;&gt;.<a href="C.Generic.Inner.html" title="class in pk\
+ g">Inner</a>.<a href="C.Generic.Inner.Foo.html" title="class in pkg">Foo</a></sp\
+ an>&nbsp;<span class="element-name">nestedGeneric2</span><wbr><span class="param\
+ eters">(<a href="C.Generic.html" title="class in pkg">C.Generic</a>&lt;java.lang\
+ .Integer&gt;.<a href="C.Generic.Inner.html" title="class in pkg">Inner</a>.<a hr\
+ ef="C.Generic.Inner.Foo.html" title="class in pkg">Foo</a>&nbsp;f,
+ <a href="C.Generic.html" title="class in pkg">C.Generic</a>&lt;<a href="C.F0.ht\
+ ml" title="interface in pkg">C.F0</a>&lt;<a href="C.html" title="class in pkg">C\
+ </a>&gt;&gt;.<a href="C.Generic.Inner.html" title="class in pkg">Inner</a>.<a hr\
+ ef="C.Generic.Inner.Foo.html" title="class in pkg">Foo</a>&nbsp;g)</span></div>""");
}
}
diff --git a/test/langtools/jdk/javadoc/doclet/testMethodSignature/pkg/C.java b/test/langtools/jdk/javadoc/doclet/testMethodSignature/pkg/C.java
index 604299e2e16..3fe053ba3f8 100644
--- a/test/langtools/jdk/javadoc/doclet/testMethodSignature/pkg/C.java
+++ b/test/langtools/jdk/javadoc/doclet/testMethodSignature/pkg/C.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -156,4 +156,33 @@ public class C {
F0<? extends T7> t7,
F0<? extends T8> t8)
throws IllegalArgumentException, IllegalStateException { return null; }
+
+ /**
+ * Inner classes with type arguments in enclosing classes.
+ *
+ * @param i param i
+ * @param j param j
+ * @return return value
+ */
+ public Generic<Integer>.Inner nestedGeneric1(Generic<Integer>.Inner i, Generic<C>.Inner j) { return i; }
+
+ /**
+ * Inner classes with type arguments in enclosing classes.
+ *
+ * @param f param f
+ * @param g param g
+ * @return return value
+ */
+ public Generic<C.F0<C>>.Inner.Foo nestedGeneric2(Generic<Integer>.Inner.Foo f, Generic<C.F0<C>>.Inner.Foo g) { return g; }
+
+ /**
+ * Generic class with multiple inner classes.
+ * @param <T> type parameter
+ */
+ public static class Generic<T> {
+ public class Inner {
+ T data;
+ public class Foo {}
+ }
+ }
}