Merge
This commit is contained in:
commit
7d0edb5743
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -216,6 +218,31 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
|
||||
return (n < 24) ? z ^ 0xaaaaaaaaaaaaaaaaL : z;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
*
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)));
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -973,6 +973,21 @@ public class Utils {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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();
|
||||
|
@ -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><<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>>.<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><<a href="A.html" title\
|
||||
="class in pkg1">A</a><<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>>.<a href="A.Inner.html" title="class in pkg1">Inner</a>,<wbr\
|
||||
><a href="A.SomeException.html" title="class in pkg1">A.SomeException</a>></c\
|
||||
ode></li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>""");
|
||||
|
||||
checkOutput("pkg1/C.html", true,
|
||||
"""
|
||||
Description copied from class: <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><<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>>.<a href="A.Inner.html" title="class in pkg1">Inner</a>""");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 {}
|
||||
|
||||
}
|
||||
|
||||
|
@ -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() {}
|
||||
|
||||
}
|
@ -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> <span c\
|
||||
lass="return-type"><a href="C.Generic.html" title="class in pkg">C.Generic</a>&l\
|
||||
t;java.lang.Integer>.<a href="C.Generic.Inner.html" title="class in pkg">Inne\
|
||||
r</a></span> <span class="element-name">nestedGeneric1</span><wbr><span cla\
|
||||
ss="parameters">(<a href="C.Generic.html" title="class in pkg">C.Generic</a><\
|
||||
java.lang.Integer>.<a href="C.Generic.Inner.html" title="class in pkg">Inner<\
|
||||
/a> i,
|
||||
<a href="C.Generic.html" title="class in pkg">C.Generic</a><<a href="C.html"\
|
||||
title="class in pkg">C</a>>.<a href="C.Generic.Inner.html" title="class in p\
|
||||
kg">Inner</a> j)</span></div>""",
|
||||
"""
|
||||
<div class="member-signature"><span class="modifiers">public</span> <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><<a href="C.html" titl\
|
||||
e="class in pkg">C</a>>>.<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> <span class="element-name">nestedGeneric2</span><wbr><span class="param\
|
||||
eters">(<a href="C.Generic.html" title="class in pkg">C.Generic</a><java.lang\
|
||||
.Integer>.<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> f,
|
||||
<a href="C.Generic.html" title="class in pkg">C.Generic</a><<a href="C.F0.ht\
|
||||
ml" title="interface in pkg">C.F0</a><<a href="C.html" title="class in pkg">C\
|
||||
</a>>>.<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> g)</span></div>""");
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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 {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user