# HG changeset patch # User mgronlun # Date 1568799154 -7200 # Node ID 5d1f1ff2ad55fa2cd9df52d3a0f60ed72c111784 # Parent 2654d1b665bf37e54d75ef42c44f0e59a947c9a8# Parent dfd434203aa0cd839bb8f1fc61cacc624f1690a9 Merge diff -r 2654d1b665bf -r 5d1f1ff2ad55 make/autoconf/buildjdk-spec.gmk.in --- 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 diff -r 2654d1b665bf -r 5d1f1ff2ad55 make/autoconf/spec.gmk.in --- 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 diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/os/aix/libodm_aix.cpp --- 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++) { diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/os/aix/libodm_aix.hpp --- 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(); } diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/os/aix/os_aix.cpp --- 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(); diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/os/posix/os_posix.cpp --- 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; } diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/os/solaris/os_solaris.cpp --- 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; } diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/os/windows/osThread_windows.cpp --- 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); + } +} diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/os/windows/osThread_windows.hpp --- 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. diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/os/windows/os_windows.cpp --- 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; diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/share/compiler/compileBroker.cpp --- 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() { diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp --- 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()); diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/share/jvmci/jvmciRuntime.cpp --- 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 diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/share/opto/block.hpp --- 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 diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/share/prims/jvm.cpp --- 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; } diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/share/prims/jvmtiEnv.cpp --- 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 */ diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/share/prims/jvmtiRawMonitor.cpp --- 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 ; } diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/share/runtime/objectMonitor.cpp --- 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()); } } diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/share/runtime/os.hpp --- 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); diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/share/runtime/osThread.cpp --- 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() { diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/share/runtime/osThread.hpp --- 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; diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/share/runtime/thread.cpp --- 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; } diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/share/runtime/thread.hpp --- 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 diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/hotspot/share/utilities/ostream.cpp --- 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; } } diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/java.base/aix/native/libjli/java_md_aix.c --- 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; } diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/java.base/unix/native/libjava/TimeZone_md.c --- 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) diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/java.base/unix/native/libnet/NetworkInterface.c --- 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; diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/java.desktop/aix/native/libawt/porting_aix.c --- 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] */ diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java --- 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 ; diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/java.xml/share/classes/com/sun/xml/internal/stream/StaxXMLInputSource.java --- 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. */ diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java --- 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(); + } + // @Override @DefinedBy(Api.COMPILER) public boolean handleOption(String current, Iterator remaining) { diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java --- 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. * diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java --- 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)); + } } } diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties --- 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 diff -r 2654d1b665bf -r 5d1f1ff2ad55 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/doubleconv/BignumDtoa.java --- 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. diff -r 2654d1b665bf -r 5d1f1ff2ad55 test/hotspot/jtreg/compiler/print/PrintCompileQueue.java --- /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"); + } +} diff -r 2654d1b665bf -r 5d1f1ff2ad55 test/jdk/java/awt/GradientPaint/LinearColorSpaceGradientTest.java --- 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 */ diff -r 2654d1b665bf -r 5d1f1ff2ad55 test/jdk/java/awt/Graphics2D/DrawString/XRenderElt254TextTest.java --- 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 */ diff -r 2654d1b665bf -r 5d1f1ff2ad55 test/jdk/java/nio/channels/Selector/WakeupSpeed.java --- 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; diff -r 2654d1b665bf -r 5d1f1ff2ad55 test/jdk/java/text/Format/DecimalFormat/FormatMicroBenchmark.java --- 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 diff -r 2654d1b665bf -r 5d1f1ff2ad55 test/jdk/jdk/nio/zipfs/LargeEntriesTest.java --- /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 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 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 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 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 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 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 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 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"); + } + } +} diff -r 2654d1b665bf -r 5d1f1ff2ad55 test/langtools/tools/javac/diags/examples/SourceNoSystemModulesPath.java --- /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 { } diff -r 2654d1b665bf -r 5d1f1ff2ad55 test/langtools/tools/javac/options/BCPOrSystemNotSpecified.java --- /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 log; + List 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 log; + List 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)); + } + } + } + } + } +} diff -r 2654d1b665bf -r 5d1f1ff2ad55 test/langtools/tools/javac/var_implicit_lambda/VarInImplicitLambdaNegTest01_source10.out --- 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