--- a/make/autoconf/buildjdk-spec.gmk.in Wed Sep 18 08:20:10 2019 +0200
+++ b/make/autoconf/buildjdk-spec.gmk.in Wed Sep 18 11:32:34 2019 +0200
@@ -91,7 +91,7 @@
# Save speed and disk space by not enabling debug symbols for the buildjdk
ENABLE_DEBUG_SYMBOLS := false
-# Control wether Hotspot builds gtest tests
+# Control whether Hotspot builds gtest tests
BUILD_GTEST := false
JVM_VARIANTS := server
--- a/make/autoconf/spec.gmk.in Wed Sep 18 08:20:10 2019 +0200
+++ b/make/autoconf/spec.gmk.in Wed Sep 18 11:32:34 2019 +0200
@@ -286,7 +286,7 @@
VALID_JVM_FEATURES := @VALID_JVM_FEATURES@
VALID_JVM_VARIANTS := @VALID_JVM_VARIANTS@
-# Control wether Hotspot builds gtest tests
+# Control whether Hotspot builds gtest tests
BUILD_GTEST := @BUILD_GTEST@
# Allow overriding the default hotspot library path
--- a/src/hotspot/os/aix/libodm_aix.cpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/os/aix/libodm_aix.cpp Wed Sep 18 11:32:34 2019 +0200
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2015, 2015 SAP SE. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -59,7 +59,7 @@
void odmWrapper::clean_data() { if (_data) { free(_data); _data = NULL; } }
-int odmWrapper::class_offset(char *field, bool is_aix_5)
+int odmWrapper::class_offset(const char *field, bool is_aix_5)
{
assert(has_class(), "initialization");
for (int i = 0; i < odm_class()->nelem; i++) {
--- a/src/hotspot/os/aix/libodm_aix.hpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/os/aix/libodm_aix.hpp Wed Sep 18 11:32:34 2019 +0200
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2015, 2015 SAP SE. All rights reserved.
+ * Copyright (c) 2015, 2019 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -68,13 +68,15 @@
public:
// Make sure everything gets initialized and cleaned up properly.
- explicit odmWrapper(char* odm_class_name, char* odm_path = NULL) : _odm_class((CLASS_SYMBOL)-1),
+ explicit odmWrapper(const char* odm_class_name, const char* odm_path = NULL) : _odm_class((CLASS_SYMBOL)-1),
_data(NULL), _initialized(false) {
if (!odm_loaded()) { return; }
_initialized = ((*_odm_initialize)() != -1);
if (_initialized) {
- if (odm_path) { (*_odm_set_path)(odm_path); }
- _odm_class = (*_odm_mount_class)(odm_class_name);
+ // should we free what odm_set_path returns, man page suggests it
+ // see https://www.ibm.com/support/knowledgecenter/en/ssw_aix_71/o_bostechref/odm_set_path.html
+ if (odm_path) { (*_odm_set_path)((char*)odm_path); }
+ _odm_class = (*_odm_mount_class)((char*)odm_class_name);
}
}
~odmWrapper() {
@@ -83,12 +85,12 @@
CLASS_SYMBOL odm_class() { return _odm_class; }
bool has_class() { return odm_class() != (CLASS_SYMBOL)-1; }
- int class_offset(char *field, bool is_aix_5);
+ int class_offset(const char *field, bool is_aix_5);
char* data() { return _data; }
- char* retrieve_obj(char* name = NULL) {
+ char* retrieve_obj(const char* name = NULL) {
clean_data();
- char *cnp = (char*)(void*)(*_odm_get_obj)(odm_class(), name, NULL, (name == NULL) ? ODM_NEXT : ODM_FIRST);
+ char *cnp = (char*)(void*)(*_odm_get_obj)(odm_class(), (char*) name, NULL, (name == NULL) ? ODM_NEXT : ODM_FIRST);
if (cnp != (char*)-1) { _data = cnp; }
return data();
}
--- a/src/hotspot/os/aix/os_aix.cpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/os/aix/os_aix.cpp Wed Sep 18 11:32:34 2019 +0200
@@ -4228,7 +4228,7 @@
// Unlike system(), this function can be called from signal handler. It
// doesn't block SIGINT et al.
int os::fork_and_exec(char* cmd, bool use_vfork_if_available) {
- char * argv[4] = {"sh", "-c", cmd, NULL};
+ char* argv[4] = { (char*)"sh", (char*)"-c", cmd, NULL};
pid_t pid = fork();
--- a/src/hotspot/os/posix/os_posix.cpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/os/posix/os_posix.cpp Wed Sep 18 11:32:34 2019 +0200
@@ -640,61 +640,6 @@
return;
}
-////////////////////////////////////////////////////////////////////////////////
-// interrupt support
-
-void os::interrupt(Thread* thread) {
- debug_only(Thread::check_for_dangling_thread_pointer(thread);)
- assert(thread->is_Java_thread(), "invariant");
- JavaThread* jt = (JavaThread*) thread;
- OSThread* osthread = thread->osthread();
-
- if (!osthread->interrupted()) {
- osthread->set_interrupted(true);
- // More than one thread can get here with the same value of osthread,
- // resulting in multiple notifications. We do, however, want the store
- // to interrupted() to be visible to other threads before we execute unpark().
- OrderAccess::fence();
- ParkEvent * const slp = jt->_SleepEvent ;
- if (slp != NULL) slp->unpark() ;
- }
-
- // For JSR166. Unpark even if interrupt status already was set
- jt->parker()->unpark();
-
- ParkEvent * ev = thread->_ParkEvent ;
- if (ev != NULL) ev->unpark() ;
-}
-
-bool os::is_interrupted(Thread* thread, bool clear_interrupted) {
- debug_only(Thread::check_for_dangling_thread_pointer(thread);)
-
- OSThread* osthread = thread->osthread();
-
- bool interrupted = osthread->interrupted();
-
- // NOTE that since there is no "lock" around the interrupt and
- // is_interrupted operations, there is the possibility that the
- // interrupted flag (in osThread) will be "false" but that the
- // low-level events will be in the signaled state. This is
- // intentional. The effect of this is that Object.wait() and
- // LockSupport.park() will appear to have a spurious wakeup, which
- // is allowed and not harmful, and the possibility is so rare that
- // it is not worth the added complexity to add yet another lock.
- // For the sleep event an explicit reset is performed on entry
- // to JavaThread::sleep, so there is no early return. It has also been
- // recommended not to put the interrupted flag into the "event"
- // structure because it hides the issue.
- if (interrupted && clear_interrupted) {
- osthread->set_interrupted(false);
- // consider thread->_SleepEvent->reset() ... optional optimization
- }
-
- return interrupted;
-}
-
-
-
static const struct {
int sig; const char* name;
}
@@ -2107,7 +2052,7 @@
// Optional optimization -- avoid state transitions if there's
// an interrupt pending.
- if (Thread::is_interrupted(thread, false)) {
+ if (jt->is_interrupted(false)) {
return;
}
@@ -2130,7 +2075,7 @@
// Don't wait if cannot get lock since interference arises from
// unparking. Also re-check interrupt before trying wait.
- if (Thread::is_interrupted(thread, false) ||
+ if (jt->is_interrupted(false) ||
pthread_mutex_trylock(_mutex) != 0) {
return;
}
--- a/src/hotspot/os/solaris/os_solaris.cpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/os/solaris/os_solaris.cpp Wed Sep 18 11:32:34 2019 +0200
@@ -5063,7 +5063,7 @@
Thread* thread = Thread::current();
assert(thread->is_Java_thread(), "Must be JavaThread");
JavaThread *jt = (JavaThread *)thread;
- if (Thread::is_interrupted(thread, false)) {
+ if (jt->is_interrupted(false)) {
return;
}
@@ -5088,7 +5088,7 @@
// Don't wait if cannot get lock since interference arises from
// unblocking. Also. check interrupt before trying wait
- if (Thread::is_interrupted(thread, false) ||
+ if (jt->is_interrupted(false) ||
os::Solaris::mutex_trylock(_mutex) != 0) {
return;
}
--- a/src/hotspot/os/windows/osThread_windows.cpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/os/windows/osThread_windows.cpp Wed Sep 18 11:32:34 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,12 +23,9 @@
*/
// no precompiled headers
-#include "runtime/handles.inline.hpp"
-#include "runtime/mutexLocker.hpp"
+#include "runtime/orderAccess.hpp"
#include "runtime/os.hpp"
#include "runtime/osThread.hpp"
-#include "runtime/safepoint.hpp"
-#include "runtime/vmThread.hpp"
void OSThread::pd_initialize() {
set_thread_handle(NULL);
@@ -36,8 +33,34 @@
set_interrupt_event(NULL);
}
-// TODO: this is not well encapsulated; creation and deletion of the
-// interrupt_event are done in os_win32.cpp, create_thread and
-// free_thread. Should follow pattern of Linux/Solaris code here.
void OSThread::pd_destroy() {
+ if (_interrupt_event != NULL) {
+ CloseHandle(_interrupt_event);
+ }
}
+
+// We need to specialize these to interact with the _interrupt_event.
+
+volatile bool OSThread::interrupted() {
+ return _interrupted != 0 &&
+ (WaitForSingleObject(_interrupt_event, 0) == WAIT_OBJECT_0);
+}
+
+void OSThread::set_interrupted(bool z) {
+ if (z) {
+ _interrupted = 1;
+ // More than one thread can get here with the same value of osthread,
+ // resulting in multiple notifications. We do, however, want the store
+ // to interrupted() to be visible to other threads before we post
+ // the interrupt event.
+ OrderAccess::release();
+ SetEvent(_interrupt_event);
+ }
+ else {
+ // We should only ever clear the interrupt if we are in fact interrupted,
+ // and this can only be done by the current thread on itself.
+ assert(_interrupted == 1, "invariant for clearing interrupt state");
+ _interrupted = 0;
+ ResetEvent(_interrupt_event);
+ }
+}
--- a/src/hotspot/os/windows/osThread_windows.hpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/os/windows/osThread_windows.hpp Wed Sep 18 11:32:34 2019 +0200
@@ -32,7 +32,8 @@
private:
// Win32-specific thread information
HANDLE _thread_handle; // Win32 thread handle
- HANDLE _interrupt_event; // Event signalled on thread interrupt
+ HANDLE _interrupt_event; // Event signalled on thread interrupt for use by
+ // Process.waitFor().
ThreadState _last_state;
public:
@@ -42,6 +43,11 @@
void set_thread_handle(HANDLE handle) { _thread_handle = handle; }
HANDLE interrupt_event() const { return _interrupt_event; }
void set_interrupt_event(HANDLE interrupt_event) { _interrupt_event = interrupt_event; }
+ // These are specialized on Windows to interact with the _interrupt_event.
+ // Also note that Windows does not skip these calls if we are interrupted - see
+ // LibraryCallKit::inline_native_isInterrupted
+ volatile bool interrupted();
+ void set_interrupted(bool z);
#ifndef PRODUCT
// Used for debugging, return a unique integer for each thread.
@@ -54,7 +60,6 @@
return false;
}
#endif // ASSERT
- bool is_try_mutex_enter() { return false; }
// This is a temporary fix for the thread states during
// suspend/resume until we throw away OSThread completely.
--- a/src/hotspot/os/windows/os_windows.cpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/os/windows/os_windows.cpp Wed Sep 18 11:32:34 2019 +0200
@@ -612,7 +612,9 @@
return false;
}
osthread->set_interrupt_event(interrupt_event);
- osthread->set_interrupted(false);
+ // We don't call set_interrupted(false) as it will trip the assert in there
+ // as we are not operating on the current thread. We don't need to call it
+ // because the initial state is already correct.
thread->set_osthread(osthread);
@@ -684,7 +686,6 @@
if (thread_handle == NULL) {
// Need to clean up stuff we've allocated so far
- CloseHandle(osthread->interrupt_event());
thread->set_osthread(NULL);
delete osthread;
return false;
@@ -714,7 +715,6 @@
"os::free_thread but not current thread");
CloseHandle(osthread->thread_handle());
- CloseHandle(osthread->interrupt_event());
delete osthread;
}
@@ -3485,7 +3485,6 @@
}
-
// Short sleep, direct OS call.
//
// ms = 0, means allow others (if any) to run.
@@ -3593,49 +3592,6 @@
return OS_OK;
}
-void os::interrupt(Thread* thread) {
- debug_only(Thread::check_for_dangling_thread_pointer(thread);)
- assert(thread->is_Java_thread(), "invariant");
- JavaThread* jt = (JavaThread*) thread;
- OSThread* osthread = thread->osthread();
- osthread->set_interrupted(true);
- // More than one thread can get here with the same value of osthread,
- // resulting in multiple notifications. We do, however, want the store
- // to interrupted() to be visible to other threads before we post
- // the interrupt event.
- OrderAccess::release();
- SetEvent(osthread->interrupt_event());
- // For JSR166: unpark after setting status
- jt->parker()->unpark();
-
- ParkEvent * ev = thread->_ParkEvent;
- if (ev != NULL) ev->unpark();
-
- ev = jt->_SleepEvent;
- if (ev != NULL) ev->unpark();
-}
-
-
-bool os::is_interrupted(Thread* thread, bool clear_interrupted) {
- debug_only(Thread::check_for_dangling_thread_pointer(thread);)
-
- OSThread* osthread = thread->osthread();
- // There is no synchronization between the setting of the interrupt
- // and it being cleared here. It is critical - see 6535709 - that
- // we only clear the interrupt state, and reset the interrupt event,
- // if we are going to report that we were indeed interrupted - else
- // an interrupt can be "lost", leading to spurious wakeups or lost wakeups
- // depending on the timing. By checking thread interrupt event to see
- // if the thread gets real interrupt thus prevent spurious wakeup.
- bool interrupted = osthread->interrupted() && (WaitForSingleObject(osthread->interrupt_event(), 0) == WAIT_OBJECT_0);
- if (interrupted && clear_interrupted) {
- osthread->set_interrupted(false);
- ResetEvent(osthread->interrupt_event());
- } // Otherwise leave the interrupted state alone
-
- return interrupted;
-}
-
// GetCurrentThreadId() returns DWORD
intx os::current_thread_id() { return GetCurrentThreadId(); }
@@ -5346,7 +5302,7 @@
JavaThread* thread = JavaThread::current();
// Don't wait if interrupted or already triggered
- if (Thread::is_interrupted(thread, false) ||
+ if (thread->is_interrupted(false) ||
WaitForSingleObject(_ParkEvent, 0) == WAIT_OBJECT_0) {
ResetEvent(_ParkEvent);
return;
--- a/src/hotspot/share/compiler/compileBroker.cpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/compiler/compileBroker.cpp Wed Sep 18 11:32:34 2019 +0200
@@ -557,8 +557,14 @@
}
void CompileQueue::print_tty() {
- ttyLocker ttyl;
- print(tty);
+ ResourceMark rm;
+ stringStream ss;
+ // Dump the compile queue into a buffer before locking the tty
+ print(&ss);
+ {
+ ttyLocker ttyl;
+ tty->print("%s", ss.as_string());
+ }
}
CompilerCounters::CompilerCounters() {
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Wed Sep 18 11:32:34 2019 +0200
@@ -1920,7 +1920,7 @@
else if (prev == CANCELLED) return false;
assert(ShenandoahSuspendibleWorkers, "should not get here when not using suspendible workers");
assert(prev == NOT_CANCELLED, "must be NOT_CANCELLED");
- {
+ if (Thread::current()->is_Java_thread()) {
// We need to provide a safepoint here, otherwise we might
// spin forever if a SP is pending.
ThreadBlockInVM sp(JavaThread::current());
--- a/src/hotspot/share/jvmci/jvmciRuntime.cpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp Wed Sep 18 11:32:34 2019 +0200
@@ -631,7 +631,7 @@
// The other thread may exit during this process, which is ok so return false.
return JNI_FALSE;
} else {
- return (jint) Thread::is_interrupted(receiverThread, clear_interrupted != 0);
+ return (jint) receiverThread->is_interrupted(clear_interrupted != 0);
}
JRT_END
--- a/src/hotspot/share/opto/block.hpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/opto/block.hpp Wed Sep 18 11:32:34 2019 +0200
@@ -317,7 +317,7 @@
uint find_node( const Node *n ) const;
// Find and remove n from block list
void find_remove( const Node *n );
- // Check wether the node is in the block.
+ // Check whether the node is in the block.
bool contains (const Node *n) const;
// Return the empty status of a block
--- a/src/hotspot/share/prims/jvm.cpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/prims/jvm.cpp Wed Sep 18 11:32:34 2019 +0200
@@ -2974,7 +2974,7 @@
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
}
- if (Thread::is_interrupted (THREAD, true) && !HAS_PENDING_EXCEPTION) {
+ if (thread->is_interrupted(true) && !HAS_PENDING_EXCEPTION) {
THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted");
}
@@ -3071,7 +3071,7 @@
bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL);
if (is_alive) {
// jthread refers to a live JavaThread.
- Thread::interrupt(receiver);
+ receiver->interrupt();
}
JVM_END
@@ -3084,7 +3084,7 @@
bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL);
if (is_alive) {
// jthread refers to a live JavaThread.
- return (jboolean) Thread::is_interrupted(receiver, clear_interrupted != 0);
+ return (jboolean) receiver->is_interrupted(clear_interrupted != 0);
} else {
return JNI_FALSE;
}
--- a/src/hotspot/share/prims/jvmtiEnv.cpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/prims/jvmtiEnv.cpp Wed Sep 18 11:32:34 2019 +0200
@@ -1101,7 +1101,7 @@
return err;
}
- Thread::interrupt(java_thread);
+ java_thread->interrupt();
return JVMTI_ERROR_NONE;
} /* end InterruptThread */
--- a/src/hotspot/share/prims/jvmtiRawMonitor.cpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/prims/jvmtiRawMonitor.cpp Wed Sep 18 11:32:34 2019 +0200
@@ -373,8 +373,12 @@
OrderAccess::fence() ;
// check interrupt event
- if (interruptible && Thread::is_interrupted(THREAD, true)) {
- return OM_INTERRUPTED;
+ if (interruptible) {
+ assert(THREAD->is_Java_thread(), "Only JavaThreads can be interruptible");
+ JavaThread* jt = (JavaThread*) THREAD;
+ if (jt->is_interrupted(true)) {
+ return OM_INTERRUPTED;
+ }
}
intptr_t save = _recursions ;
@@ -401,8 +405,11 @@
}
guarantee (THREAD == _owner, "invariant") ;
- if (interruptible && Thread::is_interrupted(THREAD, true)) {
- return OM_INTERRUPTED;
+ if (interruptible) {
+ JavaThread* jt = (JavaThread*) THREAD;
+ if (jt->is_interrupted(true)) {
+ return OM_INTERRUPTED;
+ }
}
return OM_OK ;
}
--- a/src/hotspot/share/runtime/objectMonitor.cpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/runtime/objectMonitor.cpp Wed Sep 18 11:32:34 2019 +0200
@@ -1205,7 +1205,7 @@
EventJavaMonitorWait event;
// check for a pending interrupt
- if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {
+ if (interruptible && jt->is_interrupted(true) && !HAS_PENDING_EXCEPTION) {
// post monitor waited event. Note that this is past-tense, we are done waiting.
if (JvmtiExport::should_post_monitor_waited()) {
// Note: 'false' parameter is passed here because the
@@ -1275,7 +1275,7 @@
// Thread is in thread_blocked state and oop access is unsafe.
jt->set_suspend_equivalent();
- if (interruptible && (Thread::is_interrupted(THREAD, false) || HAS_PENDING_EXCEPTION)) {
+ if (interruptible && (jt->is_interrupted(false) || HAS_PENDING_EXCEPTION)) {
// Intentionally empty
} else if (node._notified == 0) {
if (millis <= 0) {
@@ -1401,7 +1401,7 @@
if (!WasNotified) {
// no, it could be timeout or Thread.interrupt() or both
// check for interrupt event, otherwise it is timeout
- if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {
+ if (interruptible && jt->is_interrupted(true) && !HAS_PENDING_EXCEPTION) {
THROW(vmSymbols::java_lang_InterruptedException());
}
}
--- a/src/hotspot/share/runtime/os.hpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/runtime/os.hpp Wed Sep 18 11:32:34 2019 +0200
@@ -480,9 +480,6 @@
static OSReturn set_priority(Thread* thread, ThreadPriority priority);
static OSReturn get_priority(const Thread* const thread, ThreadPriority& priority);
- static void interrupt(Thread* thread);
- static bool is_interrupted(Thread* thread, bool clear_interrupted);
-
static int pd_self_suspend_thread(Thread* thread);
static ExtendedPC fetch_frame_from_context(const void* ucVoid, intptr_t** sp, intptr_t** fp);
--- a/src/hotspot/share/runtime/osThread.cpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/runtime/osThread.cpp Wed Sep 18 11:32:34 2019 +0200
@@ -30,7 +30,7 @@
pd_initialize();
set_start_proc(start_proc);
set_start_parm(start_parm);
- set_interrupted(false);
+ _interrupted = 0;
}
OSThread::~OSThread() {
--- a/src/hotspot/share/runtime/osThread.hpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/runtime/osThread.hpp Wed Sep 18 11:32:34 2019 +0200
@@ -82,10 +82,11 @@
void set_start_proc(OSThreadStartFunc start_proc) { _start_proc = start_proc; }
void* start_parm() const { return _start_parm; }
void set_start_parm(void* start_parm) { _start_parm = start_parm; }
-
+ // These are specialized on Windows.
+#ifndef _WINDOWS
volatile bool interrupted() const { return _interrupted != 0; }
void set_interrupted(bool z) { _interrupted = z ? 1 : 0; }
-
+#endif
// Printing
void print_on(outputStream* st) const;
void print() const;
--- a/src/hotspot/share/runtime/thread.cpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/runtime/thread.cpp Wed Sep 18 11:32:34 2019 +0200
@@ -856,19 +856,6 @@
return true;
}
-void Thread::interrupt(Thread* thread) {
- debug_only(check_for_dangling_thread_pointer(thread);)
- os::interrupt(thread);
-}
-
-bool Thread::is_interrupted(Thread* thread, bool clear_interrupted) {
- debug_only(check_for_dangling_thread_pointer(thread);)
- // Note: If clear_interrupted==false, this simply fetches and
- // returns the value of the field osthread()->interrupted().
- return os::is_interrupted(thread, clear_interrupted);
-}
-
-
// GC Support
bool Thread::claim_par_threads_do(uintx claim_token) {
uintx token = _threads_do_token;
@@ -1726,6 +1713,56 @@
assert(deferred_card_mark().is_empty(), "Default MemRegion ctor");
}
+
+// interrupt support
+
+void JavaThread::interrupt() {
+ debug_only(check_for_dangling_thread_pointer(this);)
+
+ if (!osthread()->interrupted()) {
+ osthread()->set_interrupted(true);
+ // More than one thread can get here with the same value of osthread,
+ // resulting in multiple notifications. We do, however, want the store
+ // to interrupted() to be visible to other threads before we execute unpark().
+ OrderAccess::fence();
+
+ // For JavaThread::sleep. Historically we only unpark if changing to the interrupted
+ // state, in contrast to the other events below. Not clear exactly why.
+ _SleepEvent->unpark();
+ }
+
+ // For JSR166. Unpark even if interrupt status already was set.
+ parker()->unpark();
+
+ // For ObjectMonitor and JvmtiRawMonitor
+ _ParkEvent->unpark();
+}
+
+
+bool JavaThread::is_interrupted(bool clear_interrupted) {
+ debug_only(check_for_dangling_thread_pointer(this);)
+ bool interrupted = osthread()->interrupted();
+
+ // NOTE that since there is no "lock" around the interrupt and
+ // is_interrupted operations, there is the possibility that the
+ // interrupted flag (in osThread) will be "false" but that the
+ // low-level events will be in the signaled state. This is
+ // intentional. The effect of this is that Object.wait() and
+ // LockSupport.park() will appear to have a spurious wakeup, which
+ // is allowed and not harmful, and the possibility is so rare that
+ // it is not worth the added complexity to add yet another lock.
+ // For the sleep event an explicit reset is performed on entry
+ // to JavaThread::sleep, so there is no early return. It has also been
+ // recommended not to put the interrupted flag into the "event"
+ // structure because it hides the issue.
+ if (interrupted && clear_interrupted) {
+ osthread()->set_interrupted(false);
+ // consider thread->_SleepEvent->reset() ... optional optimization
+ }
+
+ return interrupted;
+}
+
bool JavaThread::reguard_stack(address cur_sp) {
if (_stack_guard_state != stack_guard_yellow_reserved_disabled
&& _stack_guard_state != stack_guard_reserved_disabled) {
@@ -2370,8 +2407,8 @@
}
- // Interrupt thread so it will wake up from a potential wait()
- Thread::interrupt(this);
+ // Interrupt thread so it will wake up from a potential wait()/sleep()/park()
+ this->interrupt();
}
// External suspension mechanism.
@@ -3361,7 +3398,7 @@
for (;;) {
// interruption has precedence over timing out
- if (os::is_interrupted(this, true)) {
+ if (this->is_interrupted(true)) {
return false;
}
@@ -3389,7 +3426,7 @@
// time moving backwards, should only happen if no monotonic clock
// not a guarantee() because JVM should not abort on kernel/glibc bugs
assert(!os::supports_monotonic_clock(),
- "unexpected time moving backwards detected in os::sleep()");
+ "unexpected time moving backwards detected in JavaThread::sleep()");
} else {
millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC;
}
--- a/src/hotspot/share/runtime/thread.hpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/runtime/thread.hpp Wed Sep 18 11:32:34 2019 +0200
@@ -514,8 +514,6 @@
static void set_priority(Thread* thread, ThreadPriority priority);
static ThreadPriority get_priority(const Thread* const thread);
static void start(Thread* thread);
- static void interrupt(Thread* thr);
- static bool is_interrupted(Thread* thr, bool clear_interrupted);
void set_native_thread_name(const char *name) {
assert(Thread::current() == this, "set_native_thread_name can only be called on the current thread");
@@ -2055,9 +2053,14 @@
InstanceKlass* _class_to_be_initialized;
// java.lang.Thread.sleep support
+ ParkEvent * _SleepEvent;
public:
- ParkEvent * _SleepEvent;
bool sleep(jlong millis);
+
+ // java.lang.Thread interruption support
+ void interrupt();
+ bool is_interrupted(bool clear_interrupted);
+
};
// Inline implementation of JavaThread::current
--- a/src/hotspot/share/utilities/ostream.cpp Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/utilities/ostream.cpp Wed Sep 18 11:32:34 2019 +0200
@@ -99,13 +99,14 @@
result_len = strlen(result);
if (add_cr && result_len >= buflen) result_len = buflen-1; // truncate
} else {
- int written = os::vsnprintf(buffer, buflen, format, ap);
- assert(written >= 0, "vsnprintf encoding error");
+ int required_len = os::vsnprintf(buffer, buflen, format, ap);
+ assert(required_len >= 0, "vsnprintf encoding error");
result = buffer;
- if ((size_t)written < buflen) {
- result_len = written;
+ if ((size_t)required_len < buflen) {
+ result_len = required_len;
} else {
- DEBUG_ONLY(warning("increase O_BUFLEN in ostream.hpp -- output truncated");)
+ DEBUG_ONLY(warning("outputStream::do_vsnprintf output truncated -- buffer length is %d bytes but %d bytes are needed.",
+ add_cr ? (int)buflen + 1 : (int)buflen, add_cr ? required_len + 2 : required_len + 1);)
result_len = buflen - 1;
}
}
--- a/src/java.base/aix/native/libjli/java_md_aix.c Wed Sep 18 08:20:10 2019 +0200
+++ b/src/java.base/aix/native/libjli/java_md_aix.c Wed Sep 18 11:32:34 2019 +0200
@@ -39,8 +39,7 @@
memset((void *)info, 0, sizeof(Dl_info));
for (;;) {
if (addr >= p->ldinfo_textorg &&
- addr < (((char*)p->ldinfo_textorg) + p->ldinfo_textsize))
- {
+ addr < p->ldinfo_textorg + p->ldinfo_textsize) {
info->dli_fname = p->ldinfo_filename;
return 1;
}
--- a/src/java.base/unix/native/libjava/TimeZone_md.c Wed Sep 18 08:20:10 2019 +0200
+++ b/src/java.base/unix/native/libjava/TimeZone_md.c Wed Sep 18 11:32:34 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, 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
@@ -42,6 +42,8 @@
#include "jvm.h"
#include "TimeZone_md.h"
+static char *isFileIdentical(char* buf, size_t size, char *pathname);
+
#define SKIP_SPACE(p) while (*p == ' ' || *p == '\t') p++;
#define RESTARTABLE(_cmd, _result) do { \
@@ -72,6 +74,8 @@
static const char *DEFAULT_ZONEINFO_FILE = "/usr/share/lib/zoneinfo/localtime";
#endif /* defined(__linux__) || defined(_ALLBSD_SOURCE) */
+static const char popularZones[][4] = {"UTC", "GMT"};
+
#if defined(_AIX)
static const char *ETC_ENVIRONMENT_FILE = "/etc/environment";
#endif
@@ -121,14 +125,27 @@
findZoneinfoFile(char *buf, size_t size, const char *dir)
{
DIR *dirp = NULL;
- struct stat64 statbuf;
struct dirent *dp = NULL;
char *pathname = NULL;
- int fd = -1;
- char *dbuf = NULL;
char *tz = NULL;
int res;
+ if (strcmp(dir, ZONEINFO_DIR) == 0) {
+ /* fast path for 1st iteration */
+ for (unsigned int i = 0; i < sizeof (popularZones) / sizeof (popularZones[0]); i++) {
+ pathname = getPathName(dir, popularZones[i]);
+ if (pathname == NULL) {
+ continue;
+ }
+ tz = isFileIdentical(buf, size, pathname);
+ free((void *) pathname);
+ pathname = NULL;
+ if (tz != NULL) {
+ return tz;
+ }
+ }
+ }
+
dirp = opendir(dir);
if (dirp == NULL) {
return NULL;
@@ -162,58 +179,67 @@
if (pathname == NULL) {
break;
}
- RESTARTABLE(stat64(pathname, &statbuf), res);
- if (res == -1) {
- break;
- }
- if (S_ISDIR(statbuf.st_mode)) {
- tz = findZoneinfoFile(buf, size, pathname);
- if (tz != NULL) {
- break;
- }
- } else if (S_ISREG(statbuf.st_mode) && (size_t)statbuf.st_size == size) {
- dbuf = (char *) malloc(size);
- if (dbuf == NULL) {
- break;
- }
- RESTARTABLE(open(pathname, O_RDONLY), fd);
- if (fd == -1) {
- break;
- }
- RESTARTABLE(read(fd, dbuf, size), res);
- if (res != (ssize_t) size) {
- break;
- }
- if (memcmp(buf, dbuf, size) == 0) {
- tz = getZoneName(pathname);
- if (tz != NULL) {
- tz = strdup(tz);
- }
- break;
- }
- free((void *) dbuf);
- dbuf = NULL;
- (void) close(fd);
- fd = -1;
- }
+ tz = isFileIdentical(buf, size, pathname);
free((void *) pathname);
pathname = NULL;
+ if (tz != NULL) {
+ break;
+ }
}
if (dirp != NULL) {
(void) closedir(dirp);
}
- if (pathname != NULL) {
- free((void *) pathname);
+ return tz;
+}
+
+/*
+ * Checks if the file pointed to by pathname matches
+ * the data contents in buf.
+ * Returns a representation of the timezone file name
+ * if file match is found, otherwise NULL.
+ */
+static char *
+isFileIdentical(char *buf, size_t size, char *pathname)
+{
+ char *possibleMatch = NULL;
+ struct stat64 statbuf;
+ char *dbuf = NULL;
+ int fd = -1;
+ int res;
+
+ RESTARTABLE(stat64(pathname, &statbuf), res);
+ if (res == -1) {
+ return NULL;
}
- if (fd != -1) {
+
+ if (S_ISDIR(statbuf.st_mode)) {
+ possibleMatch = findZoneinfoFile(buf, size, pathname);
+ } else if (S_ISREG(statbuf.st_mode) && (size_t)statbuf.st_size == size) {
+ dbuf = (char *) malloc(size);
+ if (dbuf == NULL) {
+ return NULL;
+ }
+ RESTARTABLE(open(pathname, O_RDONLY), fd);
+ if (fd == -1) {
+ goto freedata;
+ }
+ RESTARTABLE(read(fd, dbuf, size), res);
+ if (res != (ssize_t) size) {
+ goto freedata;
+ }
+ if (memcmp(buf, dbuf, size) == 0) {
+ possibleMatch = getZoneName(pathname);
+ if (possibleMatch != NULL) {
+ possibleMatch = strdup(possibleMatch);
+ }
+ }
+ freedata:
+ free((void *) dbuf);
(void) close(fd);
}
- if (dbuf != NULL) {
- free((void *) dbuf);
- }
- return tz;
+ return possibleMatch;
}
#if defined(__linux__) || defined(MACOSX)
--- a/src/java.base/unix/native/libnet/NetworkInterface.c Wed Sep 18 08:20:10 2019 +0200
+++ b/src/java.base/unix/native/libnet/NetworkInterface.c Wed Sep 18 11:32:34 2019 +0200
@@ -1394,6 +1394,10 @@
/** AIX **/
#if defined(_AIX)
+/* seems getkerninfo is guarded by _KERNEL in the system headers */
+/* see net/proto_uipc.h */
+int getkerninfo(int, char *, int *, int32long64_t);
+
/*
* Opens a socket for further ioctl calls. Tries AF_INET socket first and
* if it fails return AF_INET6 socket.
@@ -1613,7 +1617,7 @@
return -1;
}
- if (getkerninfo(KINFO_NDD, nddp, &size, 0) < 0) {
+ if (getkerninfo(KINFO_NDD, (char*) nddp, &size, 0) < 0) {
perror("getkerninfo 2");
free(nddp);
return -1;
--- a/src/java.desktop/aix/native/libawt/porting_aix.c Wed Sep 18 08:20:10 2019 +0200
+++ b/src/java.desktop/aix/native/libawt/porting_aix.c Wed Sep 18 11:32:34 2019 +0200
@@ -43,11 +43,10 @@
static int dladdr_dont_reload(void* addr, Dl_info* info) {
const struct ld_info* p = (struct ld_info*) dladdr_buffer;
- info->dli_fbase = 0; info->dli_fname = 0;
- info->dli_sname = 0; info->dli_saddr = 0;
+ memset((void *)info, 0, sizeof(Dl_info));
for (;;) {
if (addr >= p->ldinfo_textorg &&
- addr < (((char*)p->ldinfo_textorg) + p->ldinfo_textsize)) {
+ addr < p->ldinfo_textorg + p->ldinfo_textsize) {
info->dli_fname = p->ldinfo_filename;
info->dli_fbase = p->ldinfo_textorg;
return 1; /* [sic] */
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java Wed Sep 18 08:20:10 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java Wed Sep 18 11:32:34 2019 +0200
@@ -3026,7 +3026,7 @@
return XMLEvent.ENTITY_REFERENCE;
}
}
- //Wether it was character reference, entity reference or built-in entity
+ //Whether it was character reference, entity reference or built-in entity
//set the next possible state to SCANNER_STATE_CONTENT
setScannerState(SCANNER_STATE_CONTENT);
fLastSectionWasEntityReference = true ;
--- a/src/java.xml/share/classes/com/sun/xml/internal/stream/StaxXMLInputSource.java Wed Sep 18 08:20:10 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/xml/internal/stream/StaxXMLInputSource.java Wed Sep 18 11:32:34 2019 +0200
@@ -33,7 +33,7 @@
*
* @author Neeraj
*
- * This class wraps XMLInputSource and is also capable of telling wether application
+ * This class wraps XMLInputSource and is also capable of telling whether application
* returned XMLStreamReader or not when XMLResolver.resolveEntity
* was called.
*/
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java Wed Sep 18 08:20:10 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java Wed Sep 18 11:32:34 2019 +0200
@@ -198,6 +198,10 @@
return locations.isDefaultBootClassPath();
}
+ public boolean isDefaultSystemModulesPath() {
+ return locations.isDefaultSystemModulesPath();
+ }
+
// <editor-fold defaultstate="collapsed" desc="Option handling">
@Override @DefinedBy(Api.COMPILER)
public boolean handleOption(String current, Iterator<String> remaining) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Wed Sep 18 08:20:10 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Wed Sep 18 11:32:34 2019 +0200
@@ -94,6 +94,7 @@
import com.sun.tools.javac.util.Pair;
import com.sun.tools.javac.util.StringUtils;
+import static javax.tools.StandardLocation.SYSTEM_MODULES;
import static javax.tools.StandardLocation.PLATFORM_CLASS_PATH;
import static com.sun.tools.javac.main.Option.BOOT_CLASS_PATH;
@@ -185,6 +186,12 @@
return h.isDefault();
}
+ boolean isDefaultSystemModulesPath() {
+ SystemModulesLocationHandler h
+ = (SystemModulesLocationHandler) getHandler(SYSTEM_MODULES);
+ return !h.isExplicit();
+ }
+
/**
* Split a search path into its elements. Empty path elements will be ignored.
*
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Wed Sep 18 08:20:10 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Wed Sep 18 11:32:34 2019 +0200
@@ -565,8 +565,13 @@
boolean lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option);
if (lintOptions && source.compareTo(Source.DEFAULT) < 0 && !options.isSet(Option.RELEASE)) {
if (fm instanceof BaseFileManager) {
- if (((BaseFileManager) fm).isDefaultBootClassPath())
- log.warning(LintCategory.OPTIONS, Warnings.SourceNoBootclasspath(source.name));
+ if (source.compareTo(Source.JDK8) <= 0) {
+ if (((BaseFileManager) fm).isDefaultBootClassPath())
+ log.warning(LintCategory.OPTIONS, Warnings.SourceNoBootclasspath(source.name));
+ } else {
+ if (((BaseFileManager) fm).isDefaultSystemModulesPath())
+ log.warning(LintCategory.OPTIONS, Warnings.SourceNoSystemModulesPath(source.name));
+ }
}
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Sep 18 08:20:10 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Sep 18 11:32:34 2019 +0200
@@ -1866,6 +1866,10 @@
bootstrap class path not set in conjunction with -source {0}
# 0: string
+compiler.warn.source.no.system.modules.path=\
+ system modules path not set in conjunction with -source {0}
+
+# 0: string
compiler.warn.option.obsolete.source=\
source value {0} is obsolete and will be removed in a future release
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/doubleconv/BignumDtoa.java Wed Sep 18 08:20:10 2019 +0200
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/doubleconv/BignumDtoa.java Wed Sep 18 11:32:34 2019 +0200
@@ -280,7 +280,7 @@
// Let v = numerator / denominator < 10.
// Then we generate 'count' digits of d = x.xxxxx... (without the decimal point)
- // from left to right. Once 'count' digits have been produced we decide wether
+ // from left to right. Once 'count' digits have been produced we decide whether
// to round up or down. Remainders of exactly .5 round upwards. Numbers such
// as 9.999999 propagate a carry all the way, and change the
// exponent (decimal_point), when rounding upwards.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/print/PrintCompileQueue.java Wed Sep 18 11:32:34 2019 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019, Loongson Technology Co. Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8230943
+ * @summary possible deadlock was detected when ran with -XX:+CIPrintCompileQueue
+ * @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+CIPrintCompileQueue
+ * compiler.print.PrintCompileQueue
+ *
+ */
+
+package compiler.print;
+
+public class PrintCompileQueue {
+ public static void main(String[] args) {
+ System.out.println("Passed");
+ }
+}
--- a/test/jdk/java/awt/GradientPaint/LinearColorSpaceGradientTest.java Wed Sep 18 08:20:10 2019 +0200
+++ b/test/jdk/java/awt/GradientPaint/LinearColorSpaceGradientTest.java Wed Sep 18 11:32:34 2019 +0200
@@ -30,7 +30,7 @@
* @test
* @key headful
* @bug 8023483
- * @summary tests wether the colorspace-parameter is applied correctly when
+ * @summary tests whether the colorspace-parameter is applied correctly when
* creating a gradient.
* @author ceisserer
*/
--- a/test/jdk/java/awt/Graphics2D/DrawString/XRenderElt254TextTest.java Wed Sep 18 08:20:10 2019 +0200
+++ b/test/jdk/java/awt/Graphics2D/DrawString/XRenderElt254TextTest.java Wed Sep 18 11:32:34 2019 +0200
@@ -33,7 +33,7 @@
* @test
* @key headful
* @bug 8028722
- * @summary tests wether drawString with 254 characters causes the xrender
+ * @summary tests whether drawString with 254 characters causes the xrender
* pipeline to hang.
* @author ceisserer
*/
--- a/test/jdk/java/nio/channels/Selector/WakeupSpeed.java Wed Sep 18 08:20:10 2019 +0200
+++ b/test/jdk/java/nio/channels/Selector/WakeupSpeed.java Wed Sep 18 11:32:34 2019 +0200
@@ -23,7 +23,7 @@
/* @test
* @bug 4467968
- * @summary Tests wether wakeup makes the next select() call return immediately
+ * @summary Tests whether wakeup makes the next select() call return immediately
*/
import java.io.IOException;
--- a/test/jdk/java/text/Format/DecimalFormat/FormatMicroBenchmark.java Wed Sep 18 08:20:10 2019 +0200
+++ b/test/jdk/java/text/Format/DecimalFormat/FormatMicroBenchmark.java Wed Sep 18 11:32:34 2019 +0200
@@ -87,7 +87,7 @@
*
* Note that these benchmarks will provide numbers without any knowledge of
* the implementation of DecimalFormat class. So to check regression any run
- * should be compared to another reference run with a previous JDK, wether or
+ * should be compared to another reference run with a previous JDK, whether or
* not this previous reference JDK contains fast-path implementation.
*
* The eight benchmarks below are dedicated to measure throughput on different
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/nio/zipfs/LargeEntriesTest.java Wed Sep 18 11:32:34 2019 +0200
@@ -0,0 +1,541 @@
+/*
+ * Copyright (c) 2019, 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.
+ *
+ */
+
+import org.testng.annotations.*;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.FileSystem;
+import java.nio.file.*;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import static java.lang.Boolean.TRUE;
+import static java.lang.String.format;
+import static java.util.stream.Collectors.joining;
+import static org.testng.Assert.*;
+
+/**
+ * @test
+ * @bug 8230870
+ * @summary Test ZIP Filesystem behavior with ~64k entries
+ * @modules jdk.zipfs
+ * @run testng LargeEntriesTest
+ */
+public class LargeEntriesTest {
+
+ private static final Path HERE = Path.of(".");
+
+ /**
+ * Number of ZIP entries which results in the use of ZIP64
+ */
+ private static final int ZIP64_ENTRIES = 65535;
+
+ /**
+ * Classes and MANIFEST attribute used for invoking Main via java -jar
+ */
+ private static final String MANIFEST_MAIN_CLASS = "LargeEntriesTest$Main";
+ private static final String MAIN_CLASS = "LargeEntriesTest$Main.class";
+ private static final String THIS_CLASS = "LargeEntriesTest.class";
+
+ /**
+ * Number of entries included in the JAR file including META-INF,
+ * MANIFEST.MF, and the classes associated with this test
+ */
+ private static final int ADDITIONAL_JAR_ENTRIES = 4;
+
+ /**
+ * Value used for creating the required entries in a ZIP or JAR file
+ */
+ private static final String ZIP_FILE_VALUE = "US Open 2019";
+ private static final byte[] ZIP_FILE_ENTRY =
+ ZIP_FILE_VALUE.getBytes(StandardCharsets.UTF_8);
+
+ /**
+ * Location of the classes to be added to the JAR file
+ */
+ static final Path TEST_CLASSES = Paths.get(System.getProperty("test.classes", "."));
+
+ private static final SecureRandom random = new SecureRandom();
+
+ /**
+ * Fields used for timing runs
+ */
+ private static int testNumberRunning;
+ private static long runningTestTime;
+ private static long startTestRunTime;
+ private static final double NANOS_IN_SECOND = 1_000_000_000.0;
+
+ @BeforeTest(enabled = false)
+ public void beforeTest() {
+ startTestRunTime = System.nanoTime();
+ }
+
+ @AfterTest(enabled = false)
+ public void afterTest() {
+ long endTestRunTime = System.nanoTime();
+ long duration = endTestRunTime - startTestRunTime;
+ System.out.printf("#### Completed test run, total running time: %.4f in seconds%n",
+ duration / NANOS_IN_SECOND);
+ }
+
+ @BeforeMethod(enabled = false)
+ public static void beforeMethod() {
+ runningTestTime = System.nanoTime();
+ System.out.printf("**** Starting test number: %s%n", testNumberRunning);
+ }
+
+ @AfterMethod(enabled = false)
+ public void afterMethod() {
+ long endRunningTestTime = System.nanoTime();
+ long duration = endRunningTestTime - runningTestTime;
+ System.out.printf("**** Completed test number: %s, Time: %.4f%n",
+ testNumberRunning, duration / NANOS_IN_SECOND);
+ testNumberRunning++;
+ }
+
+ /**
+ * Validate that you can create a ZIP file with and without compression
+ * and that the ZIP file is created using ZIP64 if there are 65535 or
+ * more entries.
+ *
+ * @param env Properties used for creating the ZIP Filesystem
+ * @param compression Indicates whether the files are DEFLATED(default)
+ * or STORED
+ * @throws Exception If an error occurs during the creation, verification or
+ * deletion of the ZIP file
+ */
+ @Test(dataProvider = "zipfsMap", enabled = true)
+ public void testZip(Map<String, String> env, int compression) throws Exception {
+
+ System.out.printf("ZIP FS Map = %s, Compression mode= %s%n ",
+ formatMap(env), compression);
+
+ for (int entries = ZIP64_ENTRIES - 1; entries < ZIP64_ENTRIES + 2; entries++) {
+ Path zipfile = generatePath(HERE, "test", ".zip");
+ Files.deleteIfExists(zipfile);
+ createZipFile(zipfile, env, entries);
+ verify(zipfile, compression, entries,
+ isTrue(env, "forceZIP64End"), 0);
+ Files.deleteIfExists(zipfile);
+ }
+ }
+
+ /**
+ * Validate that when the forceZIP64End property is set to true,
+ * that ZIP64 is used.
+ *
+ * @param env Properties used for creating the ZIP Filesystem
+ * @param compression Indicates whether the files are DEFLATED(default)
+ * or STORED
+ * @throws Exception If an error occurs during the creation, verification or
+ * deletion of the ZIP file
+ */
+ @Test(dataProvider = "zip64Map", enabled = true)
+ public void testForceZIP64End(Map<String, String> env, int compression) throws Exception {
+
+ System.out.printf("ZIP FS Map = %s, Compression mode= %s%n ",
+ formatMap(env), compression);
+
+ // Generate a ZIP file path
+ Path zipfile = generatePath(HERE, "test", ".zip");
+ Files.deleteIfExists(zipfile);
+ createZipFile(zipfile, env, 1);
+ verify(zipfile, compression, 1, isTrue(env, "forceZIP64End"), 0);
+ Files.deleteIfExists(zipfile);
+ }
+
+ /**
+ * Validate that you can create a JAR file with and without compression
+ * and that the JAR file is created using ZIP64 if there are 65535 or
+ * more entries.
+ *
+ * @param env Properties used for creating the ZIP Filesystem
+ * @param compression Indicates whether the files are DEFLATED(default)
+ * or STORED
+ * @throws Exception If an error occurs during the creation, verification or
+ * deletion of the JAR file
+ */
+ @Test(dataProvider = "zipfsMap", enabled = true)
+ public void testJar(Map<String, String> env, int compression) throws Exception {
+ for (int entries = ZIP64_ENTRIES - 1; entries < ZIP64_ENTRIES + 2; entries++) {
+ Path jar = generatePath(HERE, "test", ".jar");
+
+ Files.deleteIfExists(jar);
+ createJarFile(jar, env, entries);
+
+ // Now run the Main-Class specified the Manifest
+ runJar(jar.getFileName().toString()).assertSuccess()
+ .validate(r -> assertTrue(r.output.matches("\\AMain\\Z")));
+
+ verify(jar, compression, entries, isTrue(env, "forceZIP64End"),
+ ADDITIONAL_JAR_ENTRIES);
+ Files.deleteIfExists(jar);
+ }
+ }
+
+ /**
+ * Create a ZIP File System using the specified properties and a ZIP file
+ * with the specified number of entries
+ *
+ * @param zipFile Path to the ZIP File to create
+ * @param env Properties used for creating the ZIP Filesystem
+ * @param entries Number of entries to add to the ZIP File
+ * @throws IOException If an error occurs while creating the ZIP file
+ */
+ private void createZipFile(Path zipFile, Map<String, String> env,
+ int entries) throws IOException {
+ System.out.printf("Creating file = %s%n", zipFile);
+ try (FileSystem zipfs =
+ FileSystems.newFileSystem(zipFile, env)) {
+
+ for (int i = 0; i < entries; i++) {
+ Files.writeString(zipfs.getPath("Entry-" + i), ZIP_FILE_VALUE);
+ }
+ }
+ }
+
+ /**
+ * Create a ZIP File System using the specified properties and a JAR file
+ * with the specified number of entries
+ *
+ * @param zipFile Path to the JAR File to create
+ * @param env Properties used for creating the ZIP Filesystem
+ * @param entries Number of entries to add to the JAR File
+ * @throws IOException If an error occurs while creating the JAR file
+ */
+ private void createJarFile(Path zipFile, Map<String, String> env,
+ int entries) throws IOException {
+ System.out.printf("Creating file = %s%n", zipFile);
+ String jdkVendor = System.getProperty("java.vendor");
+ String jdkVersion = System.getProperty("java.version");
+ String manifest = "Manifest-Version: 1.0"
+ + System.lineSeparator()
+ + "Main-Class: " + MANIFEST_MAIN_CLASS
+ + System.lineSeparator()
+ + "Created-By: " + jdkVersion + " (" + jdkVendor + ")";
+
+ try (FileSystem zipfs =
+ FileSystems.newFileSystem(zipFile, env);
+ InputStream in = new ByteArrayInputStream(manifest.getBytes())) {
+
+ // Get ZIP FS path to META-INF/MANIFEST.MF
+ Path metadir = zipfs.getPath("/", "META-INF");
+ Path manifestFile = metadir.resolve("MANIFEST.MF");
+
+ // Create META-INF directory if it does not already exist and
+ // add the MANIFEST.MF file
+ if (!Files.exists(metadir))
+ Files.createDirectory(zipfs.getPath("/", "META-INF"));
+ Files.copy(in, manifestFile);
+
+ // Add the needed test classes
+ Path target = zipfs.getPath("/");
+ Files.copy(TEST_CLASSES.resolve(MAIN_CLASS),
+ target.resolve(MAIN_CLASS));
+ Files.copy(TEST_CLASSES.resolve(THIS_CLASS),
+ target.resolve(THIS_CLASS));
+
+ // Add the remaining entries that are required
+ for (int i = ADDITIONAL_JAR_ENTRIES; i < entries; i++) {
+ Files.writeString(zipfs.getPath("Entry-" + i), ZIP_FILE_VALUE);
+ }
+ }
+ }
+
+ /*
+ * DataProvider used to validate that you can create a ZIP file with and
+ * without compression.
+ */
+ @DataProvider(name = "zipfsMap")
+ private Object[][] zipfsMap() {
+ return new Object[][]{
+ {Map.of("create", "true"), ZipEntry.DEFLATED},
+ {Map.of("create", "true", "noCompression", "true"),
+ ZipEntry.STORED},
+ {Map.of("create", "true", "noCompression", "false"),
+ ZipEntry.DEFLATED}
+ };
+ }
+
+ /*
+ * DataProvider used to validate that you can create a ZIP file with/without
+ * ZIP64 format extensions
+ */
+ @DataProvider(name = "zip64Map")
+ private Object[][] zip64Map() {
+ return new Object[][]{
+ {Map.of("create", "true", "forceZIP64End", "true"),
+ ZipEntry.DEFLATED},
+ {Map.of("create", "true", "noCompression", "true",
+ "forceZIP64End", "true"), ZipEntry.STORED},
+ {Map.of("create", "true", "noCompression", "false",
+ "forceZIP64End", "false"), ZipEntry.DEFLATED},
+ {Map.of("create", "true", "noCompression", "true",
+ "forceZIP64End", "false"), ZipEntry.STORED}
+ };
+ }
+
+ /**
+ * Verify that the given path is a ZIP file containing the
+ * expected entries.
+ *
+ * @param zipfile ZIP file to be validated
+ * @param method Expected Compression method: STORED or DEFLATED
+ * @param entries Number of expected entries
+ * @param isZip64Forced true if ZIP64 use is being forced; false otherwise
+ * @param start Starting number for verifying entries
+ * @throws Exception If an error occurs while examining the ZIP file
+ */
+ private static void verify(Path zipfile, int method, int entries,
+ boolean isZip64Forced, int start) throws Exception {
+ // check entries with ZIP API
+ try (ZipFile zf = new ZipFile(zipfile.toFile())) {
+ // check entry count
+ assertEquals(entries, zf.size());
+
+ // check compression method and content of each entry
+ for (int i = start; i < entries; i++) {
+ ZipEntry ze = zf.getEntry("Entry-" + i);
+ assertNotNull(ze);
+ assertEquals(method, ze.getMethod());
+ try (InputStream is = zf.getInputStream(ze)) {
+ byte[] bytes = is.readAllBytes();
+ assertTrue(Arrays.equals(bytes, ZIP_FILE_ENTRY));
+ }
+ }
+ }
+ // check entries with FileSystem API
+ try (FileSystem fs = FileSystems.newFileSystem(zipfile)) {
+
+ // check entry count
+ Path top = fs.getPath("/");
+ long count = Files.find(top, Integer.MAX_VALUE, (path, attrs) ->
+ attrs.isRegularFile() || (attrs.isDirectory() &&
+ path.getFileName() != null &&
+ path.getFileName().toString().equals("META-INF")))
+ .count();
+ assertEquals(entries, count);
+
+ // check content of each entry
+ for (int i = start; i < entries; i++) {
+ Path file = fs.getPath("Entry-" + i);
+ byte[] bytes = Files.readAllBytes(file);
+ assertTrue(Arrays.equals(bytes, ZIP_FILE_ENTRY));
+ }
+ }
+
+ // Check for a ZIP64 End of Central Directory Locator
+ boolean foundZip64 = usesZip64(zipfile.toFile());
+
+ // Is ZIP64 required?
+ boolean requireZip64 = entries >= ZIP64_ENTRIES || isZip64Forced;
+ System.out.printf(" isZip64Forced = %s, foundZip64= %s, requireZip64= %s%n",
+ isZip64Forced, foundZip64, requireZip64);
+ assertEquals(requireZip64, foundZip64);
+
+
+ }
+
+ /**
+ * Determine if the specified property name=true/"true"
+ *
+ * @param env ZIP Filesystem Map
+ * @param name property to validate
+ * @return true if the property value is set to true/"true"; false otherwise
+ */
+ private static boolean isTrue(Map<String, ?> env, String name) {
+ return "true".equals(env.get(name)) || TRUE.equals(env.get(name));
+ }
+
+ /**
+ * Check to see if the ZIP64 End of Central Directory Locator has been found
+ *
+ * @param b byte array to check for the locator in
+ * @param n starting offset for the search
+ * @return true if the Zip64 End of Central Directory Locator is found; false
+ * otherwise
+ */
+ private static boolean end64SigAt(byte[] b, int n) {
+ return b[n] == 'P' & b[n + 1] == 'K' & b[n + 2] == 6 & b[n + 3] == 6;
+ }
+
+ /**
+ * Utility method that checks the ZIP file for the use of the ZIP64
+ * End of Central Directory Locator
+ *
+ * @param zipFile ZIP file to check
+ * @return true if the ZIP64 End of Central Directory Locator is found; false
+ * otherwise
+ * * @throws Exception If an error occurs while traversing the file
+ */
+ private static boolean usesZip64(File zipFile) throws Exception {
+
+ try (RandomAccessFile raf = new RandomAccessFile(zipFile, "r")) {
+ byte[] buf = new byte[4096];
+ long seeklen = raf.length() - buf.length;
+
+ if (seeklen < 0)
+ seeklen = 0;
+ raf.seek(seeklen);
+ raf.read(buf);
+ for (int i = 0; i < buf.length - 4; i++) {
+ // Is there a ZIP64 End of Central Directory Locator?
+ if (end64SigAt(buf, i)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Generate a temporary file Path
+ *
+ * @param dir Directory used to create the path
+ * @param prefix The prefix string used to create the path
+ * @param suffix The suffix string used to create the path
+ * @return Path that was generated
+ */
+ private static Path generatePath(Path dir, String prefix, String suffix) {
+ long n = random.nextLong();
+ String s = prefix + Long.toUnsignedString(n) + suffix;
+ Path name = dir.getFileSystem().getPath(s);
+ // the generated name should be a simple file name
+ if (name.getParent() != null)
+ throw new IllegalArgumentException("Invalid prefix or suffix");
+ return dir.resolve(name);
+ }
+
+ /**
+ * Utility method to return a formatted String of the key:value entries for
+ * a Map
+ *
+ * @param env Map to format
+ * @return Formatted string of the Map entries
+ */
+ private static String formatMap(Map<String, String> env) {
+ return env.entrySet().stream()
+ .map(e -> format("(%s:%s)", e.getKey(), e.getValue()))
+ .collect(joining(", "));
+ }
+
+ /**
+ * Validates that a jar created using ZIP FS can be used by the java
+ * tool to run a program specified in the Main-Class Manifest attribute
+ *
+ * @param jarFile Name of the JAR file to specify to the -jar option
+ * @return A Result object representing the return code and output from the
+ * program that was invoked
+ */
+ private static Result runJar(String jarFile) {
+ String javaHome = System.getProperty("java.home");
+ String java = Paths.get(javaHome, "bin", "java").toString();
+ String[] cmd = {java, "-jar", jarFile};
+ String output;
+ ProcessBuilder pb = new ProcessBuilder(cmd);
+ Process p;
+ try {
+ p = pb.start();
+ output = toString(p.getInputStream(), p.getErrorStream());
+ p.waitFor();
+ } catch (IOException | InterruptedException e) {
+ throw new RuntimeException(
+ format("Error invoking: '%s', Exception= %s", pb.command(), e));
+ }
+
+ return new Result(p.exitValue(), output);
+ }
+
+ /**
+ * Utility method to combine the output and error streams for the Process
+ * started by ProcessBuilder
+ *
+ * @param is Process Outputstream
+ * @param is2 Process ErrorStream
+ * @return String representing the combination of the OutputStream & ErrorStream
+ * @throws IOException If an error occurs while combining the streams
+ */
+ private static String toString(InputStream is, InputStream is2) throws IOException {
+ try (ByteArrayOutputStream dst = new ByteArrayOutputStream();
+ InputStream concatenated = new SequenceInputStream(is, is2)) {
+ concatenated.transferTo(dst);
+ return new String(dst.toByteArray(), StandardCharsets.UTF_8);
+ }
+ }
+
+ /**
+ * Wrapper class used to verify the results from a ProcessBuilder invocation
+ */
+ private static class Result {
+ final int ec; // Return code for command that was executed
+ final String output; // Output from the command that was executed
+
+ /**
+ * Constructor
+ *
+ * @param ec Return code from the ProcessBuilder invocation
+ * @param output ProcessBuilder output to be validated
+ */
+ private Result(int ec, String output) {
+ this.ec = ec;
+ this.output = output;
+ }
+
+ /**
+ * Validate that the command that was executed completed successfully
+ *
+ * @return This Result object
+ */
+ Result assertSuccess() {
+ assertEquals(ec, 0, format("Expected ec 0, received: %s, output [%s]", ec, output));
+ return this;
+ }
+
+ /**
+ * Validate that the expected result is received
+ *
+ * @param r The operation to perform
+ * @return This Result object
+ */
+ Result validate(Consumer<Result> r) {
+ r.accept(this);
+ return this;
+ }
+ }
+
+ /**
+ * Trivial class used to validate that a JAR created using ZIP FS
+ * can be successfully executed
+ */
+ public static class Main {
+ public static void main(String[] args) {
+ System.out.print("Main");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/SourceNoSystemModulesPath.java Wed Sep 18 11:32:34 2019 +0200
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+// key: compiler.warn.source.no.system.modules.path
+// options: -source 9
+
+class SourceNoSystemModulesPath { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/options/BCPOrSystemNotSpecified.java Wed Sep 18 11:32:34 2019 +0200
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8228460
+ * @summary Verify --system is required rather than -bootclasspath for -source 9.
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.TestRunner
+ * @run main BCPOrSystemNotSpecified
+ */
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.util.EnumSet;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.Task.Expect;
+import toolbox.TestRunner;
+import toolbox.ToolBox;
+
+public class BCPOrSystemNotSpecified extends TestRunner {
+
+ private final ToolBox tb = new ToolBox();
+ private final String fileSep = System.getProperty("file.separator");
+
+ public BCPOrSystemNotSpecified() {
+ super(System.err);
+ }
+
+ public static void main(String... args) throws Exception {
+ new BCPOrSystemNotSpecified().runTests();
+ }
+
+ @Test
+ public void testSource8(Path base) throws IOException {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "package test; public class Test { } ");
+ Path classes = base.resolve("classes");
+ tb.createDirectories(classes);
+
+ List<String> log;
+ List<String> expected = Arrays.asList(
+ "- compiler.warn.source.no.bootclasspath: 8",
+ "1 warning"
+ );
+
+ log = new JavacTask(tb)
+ .options("-XDrawDiagnostics", "-source", "8")
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ if (!expected.equals(log)) {
+ throw new AssertionError("Unexpected output: " + log);
+ }
+
+ Path bcp = base.resolve("bcp");
+
+ prepareBCP(bcp);
+
+ new JavacTask(tb)
+ .options("-XDrawDiagnostics",
+ "-source", "8",
+ "-bootclasspath", bcp.toAbsolutePath().toString(),
+ "-Werror")
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ if (!expected.equals(log)) {
+ throw new AssertionError("Unexpected output: " + log);
+ }
+ }
+
+ @Test
+ public void testSource9(Path base) throws IOException {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "package test; public class Test { } ");
+ Path classes = base.resolve("classes");
+ tb.createDirectories(classes);
+
+ List<String> log;
+ List<String> expected = Arrays.asList(
+ "- compiler.warn.source.no.system.modules.path: 9",
+ "1 warning"
+ );
+
+ log = new JavacTask(tb)
+ .options("-XDrawDiagnostics",
+ "-source", "9")
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ if (!expected.equals(log)) {
+ throw new AssertionError("Unexpected output: " + log);
+ }
+
+ Path bcp = base.resolve("bcp");
+
+ prepareBCP(bcp);
+
+ log = new JavacTask(tb)
+ .options("-XDrawDiagnostics",
+ "-source", "9",
+ "-bootclasspath", bcp.toAbsolutePath().toString())
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ if (!expected.equals(log)) {
+ throw new AssertionError("Unexpected output: " + log);
+ }
+
+ new JavacTask(tb)
+ .options("-XDrawDiagnostics",
+ "-source", "9",
+ "--system", "none",
+ "--module-path", bcp.toAbsolutePath().toString(),
+ "-Werror")
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ if (!expected.equals(log)) {
+ throw new AssertionError("Unexpected output: " + log);
+ }
+
+ new JavacTask(tb)
+ .options("-XDrawDiagnostics",
+ "-source", "9",
+ "--system", System.getProperty("java.home"),
+ "-Werror")
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ if (!expected.equals(log)) {
+ throw new AssertionError("Unexpected output: " + log);
+ }
+ }
+
+ protected void runTests() throws Exception {
+ runTests(m -> new Object[] { Paths.get(m.getName()).toAbsolutePath() });
+ }
+
+ private void prepareBCP(Path target) throws IOException {
+ try (JavaFileManager jfm = ToolProvider.getSystemJavaCompiler()
+ .getStandardFileManager(null, null, null)) {
+ for (String pack : new String[] {"", "java.lang", "java.lang.annotation"}) {
+ JavaFileManager.Location javaBase =
+ jfm.getLocationForModule(StandardLocation.SYSTEM_MODULES,
+ "java.base");
+ for (JavaFileObject file : jfm.list(javaBase,
+ pack,
+ EnumSet.of(JavaFileObject.Kind.CLASS),
+ false)) {
+ Path targetDir = target.resolve(pack.replace(".", fileSep));
+ Files.createDirectories(targetDir);
+ try (InputStream in = file.openInputStream()) {
+ String sourcePath = file.getName();
+ int sepPos = sourcePath.lastIndexOf(fileSep);
+ String fileName = sourcePath.substring(sepPos + 1);
+ Files.copy(in, targetDir.resolve(fileName));
+ }
+ }
+ }
+ }
+ }
+}
--- a/test/langtools/tools/javac/var_implicit_lambda/VarInImplicitLambdaNegTest01_source10.out Wed Sep 18 08:20:10 2019 +0200
+++ b/test/langtools/tools/javac/var_implicit_lambda/VarInImplicitLambdaNegTest01_source10.out Wed Sep 18 11:32:34 2019 +0200
@@ -1,4 +1,4 @@
-- compiler.warn.source.no.bootclasspath: 10
+- compiler.warn.source.no.system.modules.path: 10
VarInImplicitLambdaNegTest01.java:12:36: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.var.syntax.in.implicit.lambda), 10, 11
VarInImplicitLambdaNegTest01.java:15:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.implicit.and.explicit.not.allowed)
VarInImplicitLambdaNegTest01.java:17:52: compiler.err.restricted.type.not.allowed.here: var