Skip to content

Commit 3b71e4d

Browse files
author
duke
committedJul 14, 2021
Automatic merge of jdk:master into master
2 parents 09ee8d6 + 7d0edb5 commit 3b71e4d

File tree

19 files changed

+314
-88
lines changed

19 files changed

+314
-88
lines changed
 

‎make/CreateJmods.gmk

+3-3
Original file line numberDiff line numberDiff line change
@@ -213,12 +213,12 @@ endif
213213

214214
ifeq ($(call isTargetOs, windows), true)
215215
ifeq ($(SHIP_DEBUG_SYMBOLS), )
216-
JMOD_FLAGS += --exclude '**{_the.*,_*.marker,*.diz,*.pdb,*.map}'
216+
JMOD_FLAGS += --exclude '**{_the.*,_*.marker*,*.diz,*.pdb,*.map}'
217217
else
218-
JMOD_FLAGS += --exclude '**{_the.*,_*.marker,*.diz,*.map}'
218+
JMOD_FLAGS += --exclude '**{_the.*,_*.marker*,*.diz,*.map}'
219219
endif
220220
else
221-
JMOD_FLAGS += --exclude '**{_the.*,_*.marker,*.diz,*.debuginfo,*.dSYM/**,*.dSYM}'
221+
JMOD_FLAGS += --exclude '**{_the.*,_*.marker*,*.diz,*.debuginfo,*.dSYM/**,*.dSYM}'
222222
endif
223223

224224
# Create jmods in the support dir and then move them into place to keep the

‎src/hotspot/share/logging/logAsyncWriter.cpp

+17-8
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,17 @@
2727
#include "logging/logFileOutput.hpp"
2828
#include "logging/logHandle.hpp"
2929
#include "runtime/atomic.hpp"
30+
#include "runtime/os.inline.hpp"
3031

3132
class AsyncLogWriter::AsyncLogLocker : public StackObj {
3233
public:
3334
AsyncLogLocker() {
3435
assert(_instance != nullptr, "AsyncLogWriter::_lock is unavailable");
35-
_instance->_lock.wait();
36+
_instance->_lock.lock();
3637
}
3738

3839
~AsyncLogLocker() {
39-
_instance->_lock.signal();
40+
_instance->_lock.unlock();
4041
}
4142
};
4243

@@ -51,7 +52,8 @@ void AsyncLogWriter::enqueue_locked(const AsyncLogMessage& msg) {
5152
}
5253

5354
_buffer.push_back(msg);
54-
_sem.signal();
55+
_data_available = true;
56+
_lock.notify();
5557
}
5658

5759
void AsyncLogWriter::enqueue(LogFileOutput& output, const LogDecorations& decorations, const char* msg) {
@@ -75,7 +77,7 @@ void AsyncLogWriter::enqueue(LogFileOutput& output, LogMessageBuffer::Iterator m
7577
}
7678

7779
AsyncLogWriter::AsyncLogWriter()
78-
: _lock(1), _sem(0), _flush_sem(0),
80+
: _flush_sem(0), _lock(), _data_available(false),
7981
_initialized(false),
8082
_stats() {
8183
if (os::create_thread(this, os::asynclog_thread)) {
@@ -125,6 +127,7 @@ void AsyncLogWriter::write() {
125127
// append meta-messages of dropped counters
126128
AsyncLogMapIterator dropped_counters_iter(logs);
127129
_stats.iterate(&dropped_counters_iter);
130+
_data_available = false;
128131
}
129132

130133
LinkedListIterator<AsyncLogMessage> it(logs.head());
@@ -152,9 +155,14 @@ void AsyncLogWriter::write() {
152155

153156
void AsyncLogWriter::run() {
154157
while (true) {
155-
// The value of a semphore cannot be negative. Therefore, the current thread falls asleep
156-
// when its value is zero. It will be waken up when new messages are enqueued.
157-
_sem.wait();
158+
{
159+
AsyncLogLocker locker;
160+
161+
while (!_data_available) {
162+
_lock.wait(0/* no timeout */);
163+
}
164+
}
165+
158166
write();
159167
}
160168
}
@@ -198,7 +206,8 @@ void AsyncLogWriter::flush() {
198206

199207
// Push directly in-case we are at logical max capacity, as this must not get dropped.
200208
_instance->_buffer.push_back(token);
201-
_instance->_sem.signal();
209+
_instance->_data_available = true;
210+
_instance->_lock.notify();
202211
}
203212

204213
_instance->_flush_sem.wait();

‎src/hotspot/share/logging/logAsyncWriter.hpp

+3-6
Original file line numberDiff line numberDiff line change
@@ -141,13 +141,10 @@ class AsyncLogWriter : public NonJavaThread {
141141
class AsyncLogLocker;
142142

143143
static AsyncLogWriter* _instance;
144-
// _lock(1) denotes a critional region.
145-
Semaphore _lock;
146-
// _sem is a semaphore whose value denotes how many messages have been enqueued.
147-
// It decreases in AsyncLogWriter::run()
148-
Semaphore _sem;
149144
Semaphore _flush_sem;
150-
145+
// Can't use a Monitor here as we need a low-level API that can be used without Thread::current().
146+
os::PlatformMonitor _lock;
147+
bool _data_available;
151148
volatile bool _initialized;
152149
AsyncLogMap _stats; // statistics for dropped messages
153150
AsyncLogBuffer _buffer;

‎src/hotspot/share/prims/jvmtiEnv.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -3135,7 +3135,10 @@ JvmtiEnv::RawMonitorEnter(JvmtiRawMonitor * rmonitor) {
31353135
// in thread.cpp.
31363136
JvmtiPendingMonitors::enter(rmonitor);
31373137
} else {
3138-
rmonitor->raw_enter(Thread::current());
3138+
Thread* thread = Thread::current();
3139+
// 8266889: raw_enter changes Java thread state, needs WXWrite
3140+
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread));
3141+
rmonitor->raw_enter(thread);
31393142
}
31403143
return JVMTI_ERROR_NONE;
31413144
} /* end RawMonitorEnter */
@@ -3167,6 +3170,8 @@ JvmtiEnv::RawMonitorExit(JvmtiRawMonitor * rmonitor) {
31673170
jvmtiError
31683171
JvmtiEnv::RawMonitorWait(JvmtiRawMonitor * rmonitor, jlong millis) {
31693172
Thread* thread = Thread::current();
3173+
// 8266889: raw_wait changes Java thread state, needs WXWrite
3174+
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread));
31703175
int r = rmonitor->raw_wait(millis, thread);
31713176

31723177
switch (r) {

‎src/java.base/share/classes/java/util/SplittableRandom.java

+47-19
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626

2727
import java.math.BigInteger;
2828
import java.util.concurrent.atomic.AtomicLong;
29+
import java.util.random.RandomGenerator;
30+
import java.util.random.RandomGenerator.SplittableGenerator;
2931
import java.util.stream.DoubleStream;
3032
import java.util.stream.IntStream;
3133
import java.util.stream.LongStream;
@@ -86,13 +88,12 @@
8688
* @author Doug Lea
8789
* @since 1.8
8890
*/
89-
@SuppressWarnings("exports")
9091
@RandomGeneratorProperties(
9192
name = "SplittableRandom",
9293
i = 64, j = 0, k = 0,
9394
equidistribution = 1
9495
)
95-
public final class SplittableRandom extends AbstractSplittableGenerator {
96+
public final class SplittableRandom implements RandomGenerator, SplittableGenerator {
9697

9798
/*
9899
* Implementation Overview.
@@ -182,6 +183,7 @@ public final class SplittableRandom extends AbstractSplittableGenerator {
182183
private SplittableRandom(long seed, long gamma) {
183184
this.seed = seed;
184185
this.gamma = gamma;
186+
this.proxy = new AbstractSplittableGeneratorProxy();
185187
}
186188

187189
/**
@@ -216,6 +218,31 @@ private static long mixGamma(long z) {
216218
return (n < 24) ? z ^ 0xaaaaaaaaaaaaaaaaL : z;
217219
}
218220

221+
/**
222+
* Proxy class to non-public RandomSupportAbstractSplittableGenerator.
223+
*/
224+
private class AbstractSplittableGeneratorProxy extends AbstractSplittableGenerator {
225+
@Override
226+
public int nextInt() {
227+
return SplittableRandom.this.nextInt();
228+
}
229+
230+
@Override
231+
public long nextLong() {
232+
return SplittableRandom.this.nextLong();
233+
}
234+
235+
@Override
236+
public java.util.SplittableRandom split(SplittableGenerator source) {
237+
return new SplittableRandom(source.nextLong(), mixGamma(source.nextLong()));
238+
}
239+
}
240+
241+
/**
242+
* Proxy object to non-public RandomSupportAbstractSplittableGenerator.
243+
*/
244+
private AbstractSplittableGeneratorProxy proxy;
245+
219246
/**
220247
* Adds gamma to seed.
221248
*/
@@ -251,6 +278,7 @@ public SplittableRandom() { // emulate defaultGen.split()
251278
long s = defaultGen.getAndAdd(2 * GOLDEN_GAMMA);
252279
this.seed = mix64(s);
253280
this.gamma = mixGamma(s + GOLDEN_GAMMA);
281+
this.proxy = new AbstractSplittableGeneratorProxy();
254282
}
255283

256284
/**
@@ -297,7 +325,7 @@ public long nextLong() {
297325
*/
298326
@Override
299327
public void nextBytes(byte[] bytes) {
300-
super.nextBytes(bytes);
328+
proxy.nextBytes(bytes);
301329
}
302330

303331
/**
@@ -307,7 +335,7 @@ public void nextBytes(byte[] bytes) {
307335
*/
308336
@Override
309337
public Stream<SplittableGenerator> splits() {
310-
return super.splits();
338+
return proxy.splits();
311339
}
312340

313341
/**
@@ -318,7 +346,7 @@ public Stream<SplittableGenerator> splits() {
318346
*/
319347
@Override
320348
public Stream<SplittableGenerator> splits(long streamSize) {
321-
return super.splits(streamSize, this);
349+
return proxy.splits(streamSize, this);
322350
}
323351

324352
/**
@@ -329,7 +357,7 @@ public Stream<SplittableGenerator> splits(long streamSize) {
329357
*/
330358
@Override
331359
public Stream<SplittableGenerator> splits(SplittableGenerator source) {
332-
return super.splits(Long.MAX_VALUE, source);
360+
return proxy.splits(Long.MAX_VALUE, source);
333361
}
334362

335363
/**
@@ -341,7 +369,7 @@ public Stream<SplittableGenerator> splits(SplittableGenerator source) {
341369
*/
342370
@Override
343371
public Stream<SplittableGenerator> splits(long streamSize, SplittableGenerator source) {
344-
return super.splits(streamSize, source);
372+
return proxy.splits(streamSize, source);
345373
}
346374

347375
/**
@@ -356,7 +384,7 @@ public Stream<SplittableGenerator> splits(long streamSize, SplittableGenerator s
356384
*/
357385
@Override
358386
public IntStream ints(long streamSize) {
359-
return super.ints(streamSize);
387+
return proxy.ints(streamSize);
360388
}
361389

362390
/**
@@ -370,7 +398,7 @@ public IntStream ints(long streamSize) {
370398
*/
371399
@Override
372400
public IntStream ints() {
373-
return super.ints();
401+
return proxy.ints();
374402
}
375403

376404
/**
@@ -390,7 +418,7 @@ public IntStream ints() {
390418
*/
391419
@Override
392420
public IntStream ints(long streamSize, int randomNumberOrigin, int randomNumberBound) {
393-
return super.ints(streamSize, randomNumberOrigin, randomNumberBound);
421+
return proxy.ints(streamSize, randomNumberOrigin, randomNumberBound);
394422
}
395423

396424
/**
@@ -410,7 +438,7 @@ public IntStream ints(long streamSize, int randomNumberOrigin, int randomNumberB
410438
*/
411439
@Override
412440
public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
413-
return super.ints(randomNumberOrigin, randomNumberBound);
441+
return proxy.ints(randomNumberOrigin, randomNumberBound);
414442
}
415443

416444
/**
@@ -425,7 +453,7 @@ public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
425453
*/
426454
@Override
427455
public LongStream longs(long streamSize) {
428-
return super.longs(streamSize);
456+
return proxy.longs(streamSize);
429457
}
430458

431459
/**
@@ -439,7 +467,7 @@ public LongStream longs(long streamSize) {
439467
*/
440468
@Override
441469
public LongStream longs() {
442-
return super.longs();
470+
return proxy.longs();
443471
}
444472

445473
/**
@@ -459,7 +487,7 @@ public LongStream longs() {
459487
*/
460488
@Override
461489
public LongStream longs(long streamSize, long randomNumberOrigin, long randomNumberBound) {
462-
return super.longs(streamSize, randomNumberOrigin, randomNumberBound);
490+
return proxy.longs(streamSize, randomNumberOrigin, randomNumberBound);
463491
}
464492

465493
/**
@@ -479,7 +507,7 @@ public LongStream longs(long streamSize, long randomNumberOrigin, long randomNum
479507
*/
480508
@Override
481509
public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
482-
return super.longs(randomNumberOrigin, randomNumberBound);
510+
return proxy.longs(randomNumberOrigin, randomNumberBound);
483511
}
484512

485513
/**
@@ -494,7 +522,7 @@ public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
494522
*/
495523
@Override
496524
public DoubleStream doubles(long streamSize) {
497-
return super.doubles(streamSize);
525+
return proxy.doubles(streamSize);
498526
}
499527

500528
/**
@@ -509,7 +537,7 @@ public DoubleStream doubles(long streamSize) {
509537
*/
510538
@Override
511539
public DoubleStream doubles() {
512-
return super.doubles();
540+
return proxy.doubles();
513541
}
514542

515543
/**
@@ -529,7 +557,7 @@ public DoubleStream doubles() {
529557
*/
530558
@Override
531559
public DoubleStream doubles(long streamSize, double randomNumberOrigin, double randomNumberBound) {
532-
return super.doubles(streamSize, randomNumberOrigin, randomNumberBound);
560+
return proxy.doubles(streamSize, randomNumberOrigin, randomNumberBound);
533561
}
534562

535563
/**
@@ -549,6 +577,6 @@ public DoubleStream doubles(long streamSize, double randomNumberOrigin, double r
549577
*/
550578
@Override
551579
public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
552-
return super.doubles(randomNumberOrigin, randomNumberBound);
580+
return proxy.doubles(randomNumberOrigin, randomNumberBound);
553581
}
554582
}

‎src/java.base/share/classes/java/util/random/RandomGenerator.java

+49-30
Original file line numberDiff line numberDiff line change
@@ -516,9 +516,10 @@ default float nextFloat() {
516516
* @throws IllegalArgumentException if {@code bound} is not
517517
* both positive and finite
518518
*
519-
* @implSpec The default implementation simply calls
520-
* {@link RandomSupport#checkBound checkBound}(bound) and then
521-
* {@link RandomSupport#boundedNextFloat boundedNextFloat}(this, bound).
519+
* @implSpec The default implementation checks that {@code bound} is a
520+
* positive finite float. Then invokes {@code nextFloat()}, scaling
521+
* the result so that the final result lies between {@code 0.0f} (inclusive)
522+
* and {@code bound} (exclusive).
522523
*/
523524
default float nextFloat(float bound) {
524525
RandomSupport.checkBound(bound);
@@ -540,9 +541,11 @@ default float nextFloat(float bound) {
540541
* or {@code bound} is not finite, or {@code origin}
541542
* is greater than or equal to {@code bound}
542543
*
543-
* @implSpec The default implementation simply calls
544-
* {@link RandomSupport#checkBound checkBound}(bound) and then
545-
* {@link RandomSupport#boundedNextFloat boundedNextFloat}(this, bound).
544+
* @implSpec The default implementation checks that {@code origin} and
545+
* {@code bound} are positive finite floats. Then invokes
546+
* {@code nextFloat()}, scaling and translating the result so that the final
547+
* result lies between {@code origin} (inclusive) and {@code bound}
548+
* (exclusive).
546549
*/
547550
default float nextFloat(float origin, float bound) {
548551
RandomSupport.checkRange(origin, bound);
@@ -577,9 +580,10 @@ default double nextDouble() {
577580
* @throws IllegalArgumentException if {@code bound} is not
578581
* both positive and finite
579582
*
580-
* @implSpec The default implementation simply calls
581-
* {@link RandomSupport#checkBound checkBound}(bound) and then
582-
* {@link RandomSupport#boundedNextDouble boundedNextDouble}(this, bound).
583+
* @implSpec The default implementation checks that {@code bound} is a
584+
* positive finite double. Then invokes {@code nextDouble()}, scaling
585+
* the result so that the final result lies between {@code 0.0} (inclusive)
586+
* and {@code bound} (exclusive).
583587
*/
584588
default double nextDouble(double bound) {
585589
RandomSupport.checkBound(bound);
@@ -601,9 +605,11 @@ default double nextDouble(double bound) {
601605
* or {@code bound} is not finite, or {@code origin}
602606
* is greater than or equal to {@code bound}
603607
*
604-
* @implSpec The default implementation simply calls
605-
* {@link RandomSupport#checkBound checkBound}(bound) and then
606-
* {@link RandomSupport#boundedNextDouble boundedNextDouble}(this, bound).
608+
* @implSpec The default implementation checks that {@code origin} and
609+
* {@code bound} are positive finite doubles. Then calls
610+
* {@code nextDouble()}, scaling and translating the result so that the final
611+
* result lies between {@code origin} (inclusive) and {@code bound}
612+
* (exclusive).
607613
*/
608614
default double nextDouble(double origin, double bound) {
609615
RandomSupport.checkRange(origin, bound);
@@ -627,16 +633,20 @@ default int nextInt() {
627633
* Returns a pseudorandomly chosen {@code int} value between zero
628634
* (inclusive) and the specified bound (exclusive).
629635
*
630-
* @param bound the upper bound (exclusive) for the returned value. Must be positive.
636+
* @param bound the upper bound (exclusive) for the returned value.
637+
* Must be positive.
631638
*
632639
* @return a pseudorandomly chosen {@code int} value between
633640
* zero (inclusive) and the bound (exclusive)
634641
*
635642
* @throws IllegalArgumentException if {@code bound} is not positive
636643
*
637-
* @implSpec The default implementation simply calls
638-
* {@link RandomSupport#checkBound checkBound}(bound) and then
639-
* {@link RandomSupport#boundedNextInt boundedNextInt}(this, bound).
644+
* @implSpec The default implementation checks that {@code bound} is a
645+
* positive {@code int}. Then invokes {@code nextInt()}, limiting the result
646+
* to be greater than or equal zero and less than {@code bound}. If {@code bound}
647+
* is a power of two then limiting is a simple masking operation. Otherwise,
648+
* the result is re-calculated by invoking {@code nextInt()} until the
649+
* result is greater than or equal zero and less than {@code bound}.
640650
*/
641651
default int nextInt(int bound) {
642652
RandomSupport.checkBound(bound);
@@ -657,9 +667,13 @@ default int nextInt(int bound) {
657667
* @throws IllegalArgumentException if {@code origin} is greater than
658668
* or equal to {@code bound}
659669
*
660-
* @implSpec The default implementation simply calls
661-
* {@link RandomSupport#checkBound(long) checkBound}(bound) and then
662-
* {@link RandomSupport#boundedNextInt(RandomGenerator, int) boundedNextInt}(this, bound).
670+
* @implSpec The default implementation checks that {@code origin} and
671+
* {@code bound} are positive {@code ints}. Then invokes {@code nextInt()},
672+
* limiting the result to be greater that or equal {@code origin} and less
673+
* than {@code bound}. If {@code bound} is a power of two then limiting is a
674+
* simple masking operation. Otherwise, the result is re-calculated by
675+
* invoking {@code nextInt()} until the result is greater than or equal
676+
* {@code origin} and less than {@code bound}.
663677
*/
664678
default int nextInt(int origin, int bound) {
665679
RandomSupport.checkRange(origin, bound);
@@ -678,16 +692,21 @@ default int nextInt(int origin, int bound) {
678692
* Returns a pseudorandomly chosen {@code long} value between zero
679693
* (inclusive) and the specified bound (exclusive).
680694
*
681-
* @param bound the upper bound (exclusive) for the returned value. Must be positive.
695+
* @param bound the upper bound (exclusive) for the returned value.
696+
* Must be positive.
682697
*
683698
* @return a pseudorandomly chosen {@code long} value between
684699
* zero (inclusive) and the bound (exclusive)
685700
*
686701
* @throws IllegalArgumentException if {@code bound} is not positive
687702
*
688-
* @implSpec The default implementation simply calls
689-
* {@link RandomSupport#checkBound checkBound}(bound) and then
690-
* {@link RandomSupport#boundedNextLong boundedNextLong}(this, bound).
703+
* @implSpec The default implementation checks that {@code bound} is a
704+
* positive {@code long}. Then invokes {@code nextLong()}, limiting the
705+
* result to be greater than or equal zero and less than {@code bound}. If
706+
* {@code bound} is a power of two then limiting is a simple masking
707+
* operation. Otherwise, the result is re-calculated by invoking
708+
* {@code nextLong()} until the result is greater than or equal zero and
709+
* less than {@code bound}.
691710
*/
692711
default long nextLong(long bound) {
693712
RandomSupport.checkBound(bound);
@@ -708,9 +727,13 @@ default long nextLong(long bound) {
708727
* @throws IllegalArgumentException if {@code origin} is greater than
709728
* or equal to {@code bound}
710729
*
711-
* @implSpec The default implementation simply calls
712-
* {@link RandomSupport#checkBound checkBound}(bound) and then
713-
* {@link RandomSupport#boundedNextLong boundedNextLong}(this, bound).
730+
* @implSpec The default implementation checks that {@code origin} and
731+
* {@code bound} are positive {@code longs}. Then invokes {@code nextLong()},
732+
* limiting the result to be greater than or equal {@code origin} and less
733+
* than {@code bound}. If {@code bound} is a power of two then limiting is a
734+
* simple masking operation. Otherwise, the result is re-calculated by
735+
* invoking {@code nextLong()} until the result is greater than or equal
736+
* {@code origin} and less than {@code bound}.
714737
*/
715738
default long nextLong(long origin, long bound) {
716739
RandomSupport.checkRange(origin, bound);
@@ -892,10 +915,6 @@ interface SplittableGenerator extends StreamableGenerator {
892915
* Returns an instance of {@link SplittableGenerator} that utilizes the
893916
* {@code name} <a href="package-summary.html#algorithms">algorithm</a>.
894917
*
895-
* @implNote Availability is determined by RandomGeneratorFactory using the
896-
* service provider API to locate implementations of the RandomGenerator
897-
* interface and filtering on the SplittableGenerator interface.
898-
*
899918
* @param name Name of random number generator
900919
* <a href="package-summary.html#algorithms">algorithm</a>
901920
*

‎src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ public static RandomGeneratorFactory<RandomGenerator> getDefault() {
374374
/**
375375
* Returns a non-empty stream of available {@link RandomGeneratorFactory RandomGeneratorFactory(s)}.
376376
*
377-
* RandomGenerators that are marked as deprecated or are not properly configured are not included in the result.
377+
* RandomGenerators that are marked as deprecated are not included in the result.
378378
*
379379
* @implSpec Availability is determined by RandomGeneratorFactory using the service provider API
380380
* to locate implementations of the RandomGenerator interface.

‎src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,13 @@ protected void addInheritedSummaryLink(TypeElement te, Element member, Content l
133133
/**
134134
* Add the parameter for the executable member.
135135
*
136-
* @param member the member to write parameter for.
137136
* @param param the parameter that needs to be written.
137+
* @param paramType the type of the parameter.
138138
* @param isVarArg true if this is a link to var arg.
139139
* @param tree the content tree to which the parameter information will be added.
140140
*/
141-
protected void addParam(ExecutableElement member, VariableElement param, TypeMirror paramType,
142-
boolean isVarArg, Content tree) {
141+
protected void addParam(VariableElement param, TypeMirror paramType, boolean isVarArg,
142+
Content tree) {
143143
Content link = writer.getLink(new HtmlLinkInfo(configuration, EXECUTABLE_MEMBER_PARAM,
144144
paramType).varargs(isVarArg));
145145
tree.add(link);
@@ -249,7 +249,7 @@ protected Content getParameters(ExecutableElement member, boolean includeAnnotat
249249
.add(" ");
250250
}
251251
}
252-
addParam(member, param, paramType,
252+
addParam(param, paramType,
253253
(paramstart == parameters.size() - 1) && member.isVarArgs(), paramTree);
254254
break;
255255
}
@@ -268,7 +268,7 @@ protected Content getParameters(ExecutableElement member, boolean includeAnnotat
268268
.add(" ");
269269
}
270270
}
271-
addParam(member, parameters.get(i), instMeth.getParameterTypes().get(i),
271+
addParam(parameters.get(i), instMeth.getParameterTypes().get(i),
272272
(i == parameters.size() - 1) && member.isVarArgs(),
273273
paramTree);
274274
}

‎src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java

+5-7
Original file line numberDiff line numberDiff line change
@@ -1075,13 +1075,11 @@ public Content seeTagToContent(Element element, DocTree see, TagletWriterImpl.Co
10751075
} else if (refMemName == null) {
10761076
// Must be a class reference since refClass is not null and refMemName is null.
10771077
if (labelContent.isEmpty()) {
1078-
if (!refClass.getTypeParameters().isEmpty() && seeText.contains("<")) {
1079-
// If this is a generic type link try to use the TypeMirror representation.
1080-
TypeMirror refType = ch.getReferencedType(see);
1081-
if (refType != null) {
1082-
return plainOrCode(isLinkPlain, getLink(
1083-
new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.DEFAULT, refType)));
1084-
}
1078+
TypeMirror referencedType = ch.getReferencedType(see);
1079+
if (utils.isGenericType(referencedType)) {
1080+
// This is a generic type link, use the TypeMirror representation.
1081+
return plainOrCode(isLinkPlain, getLink(
1082+
new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.DEFAULT, referencedType)));
10851083
}
10861084
labelContent = plainOrCode(isLinkPlain, Text.of(utils.getSimpleName(refClass)));
10871085
}

‎src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,7 @@ protected Content getClassLink(LinkInfo linkInfo) {
107107
if (utils.isIncluded(typeElement)) {
108108
if (configuration.isGeneratedDoc(typeElement) && !utils.hasHiddenTag(typeElement)) {
109109
DocPath filename = getPath(classLinkInfo);
110-
if (linkInfo.linkToSelf ||
111-
!(docPaths.forName(typeElement)).equals(m_writer.filename)) {
110+
if (linkInfo.linkToSelf || typeElement != m_writer.getCurrentPageElement()) {
112111
link.add(m_writer.links.createLink(
113112
filename.fragment(classLinkInfo.where),
114113
label,

‎src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java

+3
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ Element getElement(ReferenceTree rtree) {
192192
}
193193

194194
public TypeMirror getType(ReferenceTree rtree) {
195+
// Workaround for JDK-8269706
196+
if (path == null || dcTree == null || rtree == null)
197+
return null;
195198
DocTreePath docTreePath = DocTreePath.getPath(path, dcTree, rtree);
196199
if (docTreePath != null) {
197200
DocTrees doctrees = configuration.docEnv.getDocTrees();

‎src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java

+15
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,21 @@ public TypeElement findClassInPackageElement(PackageElement pkg, String classNam
973973
return null;
974974
}
975975

976+
/**
977+
* Returns true if {@code type} or any of its enclosing types has non-empty type arguments.
978+
* @param type the type
979+
* @return {@code true} if type arguments were found
980+
*/
981+
public boolean isGenericType(TypeMirror type) {
982+
while (type instanceof DeclaredType dt) {
983+
if (!dt.getTypeArguments().isEmpty()) {
984+
return true;
985+
}
986+
type = dt.getEnclosingType();
987+
}
988+
return false;
989+
}
990+
976991
/**
977992
* TODO: FIXME: port to javax.lang.model
978993
* Find a class within the context of this class. Search order: qualified name, in this class

‎src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkFactory.java

+16
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,16 @@ public Content visitTypeVariable(TypeVariable type, LinkInfo linkInfo) {
166166

167167
@Override
168168
public Content visitDeclared(DeclaredType type, LinkInfo linkInfo) {
169+
TypeMirror enc = type.getEnclosingType();
170+
if (enc instanceof DeclaredType dt && utils.isGenericType(dt)) {
171+
// If an enclosing type has type parameters render them as separate links as
172+
// otherwise this information is lost. On the other hand, plain enclosing types
173+
// are not linked separately as they are easy to reach from the nested type.
174+
setEnclosingTypeLinkInfo(linkInfo, dt);
175+
visitDeclared(dt, linkInfo);
176+
link.add(".");
177+
setEnclosingTypeLinkInfo(linkInfo, type);
178+
}
169179
link.add(getTypeAnnotationLinks(linkInfo));
170180
linkInfo.typeElement = utils.asTypeElement(type);
171181
link.add(getClassLink(linkInfo));
@@ -195,6 +205,12 @@ private void setBoundsLinkInfo(LinkInfo linkInfo, TypeMirror bound) {
195205
linkInfo.skipPreview = false;
196206
}
197207

208+
private void setEnclosingTypeLinkInfo(LinkInfo linkinfo, DeclaredType enclosing) {
209+
linkinfo.typeElement = null;
210+
linkinfo.label = null;
211+
linkinfo.type = enclosing;
212+
}
213+
198214
/**
199215
* Returns a link to the given class.
200216
*

‎src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkInfo.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@
2727

2828
import javax.lang.model.element.ExecutableElement;
2929
import javax.lang.model.element.TypeElement;
30+
import javax.lang.model.type.DeclaredType;
3031
import javax.lang.model.type.TypeMirror;
3132

3233
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
3334
import jdk.javadoc.internal.doclets.toolkit.Content;
35+
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
3436

3537
/**
3638
* Encapsulates information about a link.
@@ -125,7 +127,11 @@ public Content getClassLinkLabel(BaseConfiguration configuration) {
125127
return label;
126128
} else if (isLinkable()) {
127129
Content tlabel = newContent();
128-
tlabel.add(configuration.utils.getSimpleName(typeElement));
130+
Utils utils = configuration.utils;
131+
tlabel.add(type instanceof DeclaredType dt && utils.isGenericType(dt.getEnclosingType())
132+
// If enclosing type is rendered as separate links only use own class name
133+
? typeElement.getSimpleName().toString()
134+
: configuration.utils.getSimpleName(typeElement));
129135
return tlabel;
130136
} else {
131137
Content tlabel = newContent();

‎test/langtools/jdk/javadoc/doclet/testGenericTypeLink/TestGenericTypeLink.java

+35-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
/*
2525
* @test
26-
* @bug 8177280 8262992
26+
* @bug 8177280 8262992 8259499
2727
* @summary see and link tag syntax should allow generic types
2828
* @library ../../lib
2929
* @modules jdk.javadoc/jdk.javadoc.internal.tool
@@ -118,6 +118,40 @@ s or interface in java.util" class="external-link"><code>Link to generic type wi
118118
</dd>
119119
</dl>"""
120120
);
121+
checkOutput("pkg1/A.Inner.html", true,
122+
"""
123+
<dl class="notes">
124+
<dt>See Also:</dt>
125+
<dd>
126+
<ul class="see-list-long">
127+
<li><code><a href="A.html" title="class in pkg1">A</a>&lt;<a href="http://exampl\
128+
e.com/docs/api/java.base/java/lang/String.html" title="class or interface in jav\
129+
a.lang" class="external-link">String</a>,<wbr><a href="http://example.com/docs/a\
130+
pi/java.base/java/lang/RuntimeException.html" title="class or interface in java.\
131+
lang" class="external-link">RuntimeException</a>&gt;.<a href="A.Inner.html" titl\
132+
e="class in pkg1">Inner</a></code></li>
133+
<li><code><a href="A.html" title="class in pkg1">A</a>&lt;<a href="A.html" title\
134+
="class in pkg1">A</a>&lt;<a href="http://example.com/docs/api/java.base/java/la\
135+
ng/String.html" title="class or interface in java.lang" class="external-link">St\
136+
ring</a>,<wbr><a href="http://example.com/docs/api/java.base/java/lang/RuntimeEx\
137+
ception.html" title="class or interface in java.lang" class="external-link">Runt\
138+
imeException</a>&gt;.<a href="A.Inner.html" title="class in pkg1">Inner</a>,<wbr\
139+
><a href="A.SomeException.html" title="class in pkg1">A.SomeException</a>&gt;</c\
140+
ode></li>
141+
</ul>
142+
</dd>
143+
</dl>""");
144+
145+
checkOutput("pkg1/C.html", true,
146+
"""
147+
Description copied from class:&nbsp;<code><a href="A.html#overriddenMethod()">A<\
148+
/a></code></span></div>
149+
<div class="block">Here's a generic link: <code><a href="A.html" title="class in\
150+
pkg1">A</a>&lt;<a href="http://example.com/docs/api/java.base/java/lang/Object.\
151+
html" title="class or interface in java.lang" class="external-link">Object</a>,<\
152+
wbr><a href="http://example.com/docs/api/java.base/java/lang/RuntimeException.ht\
153+
ml" title="class or interface in java.lang" class="external-link">RuntimeExcepti\
154+
on</a>&gt;.<a href="A.Inner.html" title="class in pkg1">Inner</a>""");
121155
}
122156

123157
/**

‎test/langtools/jdk/javadoc/doclet/testGenericTypeLink/pkg1/A.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -60,6 +60,16 @@ public void someMethod(List<? extends Number> list, int i) {}
6060
*/
6161
public void otherMethod(Map<String, ?> list, double d) {}
6262

63+
/**
64+
* Here's a generic link: {@link A<Object, RuntimeException>.Inner}
65+
*/
66+
public void overriddenMethod() {}
67+
68+
/**
69+
* @see A<String, java.lang.RuntimeException>.Inner
70+
* @see A<A<String, java.lang.RuntimeException>.Inner, A.SomeException>
71+
*/
72+
class Inner {}
6373

6474
}
6575

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
package pkg1;
25+
26+
import java.util.Map;
27+
28+
public class C<T, E extends Exception> extends A {
29+
30+
@Override
31+
public void overriddenMethod() {}
32+
33+
}

‎test/langtools/jdk/javadoc/doclet/testMethodSignature/TestMethodSignature.java

+27-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
/*
2525
* @test
26-
* @bug 8214126 8241470
26+
* @bug 8214126 8241470 8259499
2727
* @summary Method signatures not formatted correctly in browser
2828
* @library ../../lib/
2929
* @modules jdk.javadoc/jdk.javadoc.internal.tool
@@ -123,7 +123,32 @@ public void test() {
123123
throws <span class="exc\
124124
eptions">java.lang.IllegalArgumentException,
125125
java.lang.IllegalStateException</span></div>
126-
<div class="block">Generic method with eight type args and annotation.</div>""");
126+
<div class="block">Generic method with eight type args and annotation.</div>""",
127+
"""
128+
<div class="member-signature"><span class="modifiers">public</span>&nbsp;<span c\
129+
lass="return-type"><a href="C.Generic.html" title="class in pkg">C.Generic</a>&l\
130+
t;java.lang.Integer&gt;.<a href="C.Generic.Inner.html" title="class in pkg">Inne\
131+
r</a></span>&nbsp;<span class="element-name">nestedGeneric1</span><wbr><span cla\
132+
ss="parameters">(<a href="C.Generic.html" title="class in pkg">C.Generic</a>&lt;\
133+
java.lang.Integer&gt;.<a href="C.Generic.Inner.html" title="class in pkg">Inner<\
134+
/a>&nbsp;i,
135+
<a href="C.Generic.html" title="class in pkg">C.Generic</a>&lt;<a href="C.html"\
136+
title="class in pkg">C</a>&gt;.<a href="C.Generic.Inner.html" title="class in p\
137+
kg">Inner</a>&nbsp;j)</span></div>""",
138+
"""
139+
<div class="member-signature"><span class="modifiers">public</span>&nbsp;<span c\
140+
lass="return-type"><a href="C.Generic.html" title="class in pkg">C.Generic</a>&l\
141+
t;<a href="C.F0.html" title="interface in pkg">C.F0</a>&lt;<a href="C.html" titl\
142+
e="class in pkg">C</a>&gt;&gt;.<a href="C.Generic.Inner.html" title="class in pk\
143+
g">Inner</a>.<a href="C.Generic.Inner.Foo.html" title="class in pkg">Foo</a></sp\
144+
an>&nbsp;<span class="element-name">nestedGeneric2</span><wbr><span class="param\
145+
eters">(<a href="C.Generic.html" title="class in pkg">C.Generic</a>&lt;java.lang\
146+
.Integer&gt;.<a href="C.Generic.Inner.html" title="class in pkg">Inner</a>.<a hr\
147+
ef="C.Generic.Inner.Foo.html" title="class in pkg">Foo</a>&nbsp;f,
148+
<a href="C.Generic.html" title="class in pkg">C.Generic</a>&lt;<a href="C.F0.ht\
149+
ml" title="interface in pkg">C.F0</a>&lt;<a href="C.html" title="class in pkg">C\
150+
</a>&gt;&gt;.<a href="C.Generic.Inner.html" title="class in pkg">Inner</a>.<a hr\
151+
ef="C.Generic.Inner.Foo.html" title="class in pkg">Foo</a>&nbsp;g)</span></div>""");
127152

128153
}
129154
}

‎test/langtools/jdk/javadoc/doclet/testMethodSignature/pkg/C.java

+30-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -156,4 +156,33 @@ With8Types<T1, T2, T3, T4, T5, T6, T7, T8> bigGenericAnnotatedMethod(
156156
F0<? extends T7> t7,
157157
F0<? extends T8> t8)
158158
throws IllegalArgumentException, IllegalStateException { return null; }
159+
160+
/**
161+
* Inner classes with type arguments in enclosing classes.
162+
*
163+
* @param i param i
164+
* @param j param j
165+
* @return return value
166+
*/
167+
public Generic<Integer>.Inner nestedGeneric1(Generic<Integer>.Inner i, Generic<C>.Inner j) { return i; }
168+
169+
/**
170+
* Inner classes with type arguments in enclosing classes.
171+
*
172+
* @param f param f
173+
* @param g param g
174+
* @return return value
175+
*/
176+
public Generic<C.F0<C>>.Inner.Foo nestedGeneric2(Generic<Integer>.Inner.Foo f, Generic<C.F0<C>>.Inner.Foo g) { return g; }
177+
178+
/**
179+
* Generic class with multiple inner classes.
180+
* @param <T> type parameter
181+
*/
182+
public static class Generic<T> {
183+
public class Inner {
184+
T data;
185+
public class Foo {}
186+
}
187+
}
159188
}

0 commit comments

Comments
 (0)
Please sign in to comment.