OpenJDK / jdk / jdk12
changeset 27304:03562d5f4f8b
Merge
author | duke |
---|---|
date | Wed, 05 Jul 2017 20:05:54 +0200 |
parents | 97d38ac57757 ff3103f12eda |
children | bf2ff5decbe7 |
files | jdk/src/java.base/share/conf/calendars.properties jdk/src/java.base/share/conf/hijrah-config-umalqura.properties jdk/src/java.desktop/unix/classes/META-INF/services/javax.print.PrintServiceLookup jdk/src/java.desktop/unix/classes/META-INF/services/javax.print.StreamPrintServiceFactory jdk/src/java.desktop/unix/classes/sun/print/UnixPrintServiceLookup.java jdk/src/java.desktop/windows/classes/META-INF/services/javax.print.PrintServiceLookup jdk/src/java.desktop/windows/classes/META-INF/services/javax.print.StreamPrintServiceFactory jdk/src/java.desktop/windows/classes/sun/print/Win32PrintServiceLookup.java jdk/test/java/sql/TEST.properties jdk/test/java/sql/test/sql/BatchUpdateExceptionTests.java jdk/test/java/sql/test/sql/DataTruncationTests.java jdk/test/java/sql/test/sql/DateTests.java jdk/test/java/sql/test/sql/DriverManagerPermissionsTests.java jdk/test/java/sql/test/sql/DriverManagerTests.java jdk/test/java/sql/test/sql/SQLClientInfoExceptionTests.java jdk/test/java/sql/test/sql/SQLDataExceptionTests.java jdk/test/java/sql/test/sql/SQLExceptionTests.java jdk/test/java/sql/test/sql/SQLFeatureNotSupportedExceptionTests.java jdk/test/java/sql/test/sql/SQLIntegrityConstraintViolationExceptionTests.java jdk/test/java/sql/test/sql/SQLInvalidAuthorizationSpecExceptionTests.java jdk/test/java/sql/test/sql/SQLNonTransientConnectionExceptionTests.java jdk/test/java/sql/test/sql/SQLNonTransientExceptionTests.java jdk/test/java/sql/test/sql/SQLRecoverableExceptionTests.java jdk/test/java/sql/test/sql/SQLSyntaxErrorExceptionTests.java jdk/test/java/sql/test/sql/SQLTimeoutExceptionTests.java jdk/test/java/sql/test/sql/SQLTransactionRollbackExceptionTests.java jdk/test/java/sql/test/sql/SQLTransientConnectionExceptionTests.java jdk/test/java/sql/test/sql/SQLTransientExceptionTests.java jdk/test/java/sql/test/sql/SQLWarningTests.java jdk/test/java/sql/test/sql/TimeTests.java jdk/test/java/sql/test/sql/TimestampTests.java jdk/test/java/sql/util/BaseTest.java jdk/test/java/sql/util/DriverActionImpl.java jdk/test/java/sql/util/SerializedBatchUpdateException.java jdk/test/java/sql/util/StubBlob.java jdk/test/java/sql/util/StubConnection.java jdk/test/java/sql/util/StubDriver.java jdk/test/java/sql/util/StubDriverDA.java jdk/test/java/sql/util/TestPolicy.java jdk/test/javax/sql/testng/util/BaseTest.java jdk/test/javax/sql/testng/util/TestPolicy.java |
diffstat | 267 files changed, 12846 insertions(+), 10324 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags-top-repo Thu Oct 30 08:34:51 2014 -0700 +++ b/.hgtags-top-repo Wed Jul 05 20:05:54 2017 +0200 @@ -279,3 +279,4 @@ 087b23f35631e68e950496a36fce8ccca612966a jdk9-b34 c173ba994245380fb11ef077d1e59823386840eb jdk9-b35 201d4e235d597a25a2d3ee1404394789ba386119 jdk9-b36 +723a67b0c442391447b1d8aad8b249d06d1032e8 jdk9-b37
--- a/common/autoconf/flags.m4 Thu Oct 30 08:34:51 2014 -0700 +++ b/common/autoconf/flags.m4 Wed Jul 05 20:05:54 2017 +0200 @@ -136,8 +136,8 @@ SYSROOT_CFLAGS="-isysroot \"$SYSROOT\" -iframework\"$SYSROOT/System/Library/Frameworks\"" SYSROOT_LDFLAGS=$SYSROOT_CFLAGS elif test "x$TOOLCHAIN_TYPE" = xgcc; then - SYSROOT_CFLAGS="--sysroot=\"$SYSROOT\"" - SYSROOT_LDFLAGS="--sysroot=\"$SYSROOT\"" + SYSROOT_CFLAGS="--sysroot=$SYSROOT" + SYSROOT_LDFLAGS="--sysroot=$SYSROOT" elif test "x$TOOLCHAIN_TYPE" = xclang; then SYSROOT_CFLAGS="-isysroot \"$SYSROOT\"" SYSROOT_LDFLAGS="-isysroot \"$SYSROOT\""
--- a/common/autoconf/generated-configure.sh Thu Oct 30 08:34:51 2014 -0700 +++ b/common/autoconf/generated-configure.sh Wed Jul 05 20:05:54 2017 +0200 @@ -4328,7 +4328,7 @@ #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1413533532 +DATE_WHEN_GENERATED=1414663067 ############################################################################### # @@ -41681,8 +41681,8 @@ SYSROOT_CFLAGS="-isysroot \"$SYSROOT\" -iframework\"$SYSROOT/System/Library/Frameworks\"" SYSROOT_LDFLAGS=$SYSROOT_CFLAGS elif test "x$TOOLCHAIN_TYPE" = xgcc; then - SYSROOT_CFLAGS="--sysroot=\"$SYSROOT\"" - SYSROOT_LDFLAGS="--sysroot=\"$SYSROOT\"" + SYSROOT_CFLAGS="--sysroot=$SYSROOT" + SYSROOT_LDFLAGS="--sysroot=$SYSROOT" elif test "x$TOOLCHAIN_TYPE" = xclang; then SYSROOT_CFLAGS="-isysroot \"$SYSROOT\"" SYSROOT_LDFLAGS="-isysroot \"$SYSROOT\"" @@ -44037,17 +44037,6 @@ -R$OPENWIN_HOME/lib$OPENJDK_TARGET_CPU_ISADIR" fi - # - # Weird Sol10 something check...TODO change to try compile - # - if test "x${OPENJDK_TARGET_OS}" = xsolaris; then - if test "`uname -r`" = "5.10"; then - if test "`${EGREP} -c XLinearGradient ${OPENWIN_HOME}/share/include/X11/extensions/Xrender.h`" = "0"; then - X_CFLAGS="${X_CFLAGS} -DSOLARIS10_NO_XRENDER_STRUCTS" - fi - fi - fi - ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -44055,7 +44044,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu OLD_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $X_CFLAGS" + CFLAGS="$CFLAGS $SYSROOT_CFLAGS $X_CFLAGS" # Need to include Xlib.h and Xutil.h to avoid "present but cannot be compiled" warnings on Solaris 10 for ac_header in X11/extensions/shape.h X11/extensions/Xrender.h X11/extensions/XTest.h X11/Intrinsic.h @@ -44079,6 +44068,31 @@ done + # If XLinearGradient isn't available in Xrender.h, signal that it needs to be + # defined in libawt_xawt. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if XlinearGradient is defined in Xrender.h" >&5 +$as_echo_n "checking if XlinearGradient is defined in Xrender.h... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <X11/extensions/Xrender.h> +int +main () +{ +XLinearGradient x; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + X_CFLAGS="$X_CFLAGS -DSOLARIS10_NO_XRENDER_STRUCTS" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$OLD_CFLAGS" ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS'
--- a/common/autoconf/libraries.m4 Thu Oct 30 08:34:51 2014 -0700 +++ b/common/autoconf/libraries.m4 Wed Jul 05 20:05:54 2017 +0200 @@ -139,20 +139,9 @@ -R$OPENWIN_HOME/lib$OPENJDK_TARGET_CPU_ISADIR" fi - # - # Weird Sol10 something check...TODO change to try compile - # - if test "x${OPENJDK_TARGET_OS}" = xsolaris; then - if test "`uname -r`" = "5.10"; then - if test "`${EGREP} -c XLinearGradient ${OPENWIN_HOME}/share/include/X11/extensions/Xrender.h`" = "0"; then - X_CFLAGS="${X_CFLAGS} -DSOLARIS10_NO_XRENDER_STRUCTS" - fi - fi - fi - AC_LANG_PUSH(C) OLD_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $X_CFLAGS" + CFLAGS="$CFLAGS $SYSROOT_CFLAGS $X_CFLAGS" # Need to include Xlib.h and Xutil.h to avoid "present but cannot be compiled" warnings on Solaris 10 AC_CHECK_HEADERS([X11/extensions/shape.h X11/extensions/Xrender.h X11/extensions/XTest.h X11/Intrinsic.h], @@ -164,6 +153,16 @@ ] ) + # If XLinearGradient isn't available in Xrender.h, signal that it needs to be + # defined in libawt_xawt. + AC_MSG_CHECKING([if XlinearGradient is defined in Xrender.h]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[#include <X11/extensions/Xrender.h>]], + [[XLinearGradient x;]])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + X_CFLAGS="$X_CFLAGS -DSOLARIS10_NO_XRENDER_STRUCTS"]) + CFLAGS="$OLD_CFLAGS" AC_LANG_POP(C)
--- a/hotspot/.hgtags Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/.hgtags Wed Jul 05 20:05:54 2017 +0200 @@ -439,3 +439,4 @@ 821164b0131a47ca065697c7d27d8f215e608c8d jdk9-b34 438cb613151c4bd290bb732697517cba1cafcb04 jdk9-b35 464ab653fbb17eb518d8ef60f8df301de7ef00d0 jdk9-b36 +b1c2dd843f247a1db19e1e85eb62ca405f72dc26 jdk9-b37
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -734,7 +734,7 @@ // Move class loader data from main list to the unloaded list for unloading // and deallocation later. -bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure) { +bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure, bool clean_alive) { ClassLoaderData* data = _head; ClassLoaderData* prev = NULL; bool seen_dead_loader = false; @@ -743,27 +743,9 @@ // purging and we don't want to rewalk the previously unloaded class loader data. _saved_unloading = _unloading; - // mark metadata seen on the stack and code cache so we can delete - // unneeded entries. - bool has_redefined_a_class = JvmtiExport::has_redefined_a_class(); - MetadataOnStackMark md_on_stack(has_redefined_a_class); - if (has_redefined_a_class) { - // purge_previous_versions also cleans weak method links. Because - // one method's MDO can reference another method from another - // class loader, we need to first clean weak method links for all - // class loaders here. Below, we can then free redefined methods - // for all class loaders. - while (data != NULL) { - if (data->is_alive(is_alive_closure)) { - data->classes_do(InstanceKlass::purge_previous_versions); - } - data = data->next(); - } - } data = _head; while (data != NULL) { if (data->is_alive(is_alive_closure)) { - data->free_deallocate_list(); prev = data; data = data->next(); continue; @@ -785,6 +767,11 @@ _unloading = dead; } + if (clean_alive) { + // Clean previous versions and the deallocate list. + ClassLoaderDataGraph::clean_metaspaces(); + } + if (seen_dead_loader) { post_class_unload_events(); } @@ -792,6 +779,26 @@ return seen_dead_loader; } +void ClassLoaderDataGraph::clean_metaspaces() { + // mark metadata seen on the stack and code cache so we can delete unneeded entries. + bool has_redefined_a_class = JvmtiExport::has_redefined_a_class(); + MetadataOnStackMark md_on_stack(has_redefined_a_class); + + if (has_redefined_a_class) { + // purge_previous_versions also cleans weak method links. Because + // one method's MDO can reference another method from another + // class loader, we need to first clean weak method links for all + // class loaders here. Below, we can then free redefined methods + // for all class loaders. + for (ClassLoaderData* data = _head; data != NULL; data = data->next()) { + data->classes_do(InstanceKlass::purge_previous_versions); + } + } + + // Need to purge the previous version before deallocating. + free_deallocate_lists(); +} + void ClassLoaderDataGraph::purge() { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!"); ClassLoaderData* list = _unloading; @@ -819,6 +826,14 @@ #endif } +void ClassLoaderDataGraph::free_deallocate_lists() { + for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { + // We need to keep this data until InstanceKlass::purge_previous_version has been + // called on all alive classes. See the comment in ClassLoaderDataGraph::clean_metaspaces. + cld->free_deallocate_list(); + } +} + // CDS support // Global metaspaces for writing information to the shared archive. When
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp Wed Jul 05 20:05:54 2017 +0200 @@ -71,6 +71,7 @@ static ClassLoaderData* add(Handle class_loader, bool anonymous, TRAPS); static void post_class_unload_events(void); + static void clean_metaspaces(); public: static ClassLoaderData* find_or_create(Handle class_loader, TRAPS); static void purge(); @@ -90,7 +91,7 @@ static void methods_do(void f(Method*)); static void loaded_classes_do(KlassClosure* klass_closure); static void classes_unloading_do(void f(Klass* const)); - static bool do_unloading(BoolObjectClosure* is_alive); + static bool do_unloading(BoolObjectClosure* is_alive, bool clean_alive); // CMS support. static void remember_new_clds(bool remember) { _saved_head = (remember ? _head : NULL); } @@ -106,6 +107,8 @@ } } + static void free_deallocate_lists(); + static void dump_on(outputStream * const out) PRODUCT_RETURN; static void dump() { dump_on(tty); } static void verify();
--- a/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -31,25 +31,23 @@ #include "runtime/synchronizer.hpp" #include "runtime/thread.hpp" #include "services/threadService.hpp" -#include "utilities/growableArray.hpp" - +#include "utilities/chunkedList.hpp" -// Keep track of marked on-stack metadata so it can be cleared. -GrowableArray<Metadata*>* _marked_objects = NULL; +volatile MetadataOnStackBuffer* MetadataOnStackMark::_used_buffers = NULL; +volatile MetadataOnStackBuffer* MetadataOnStackMark::_free_buffers = NULL; + NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;) // Walk metadata on the stack and mark it so that redefinition doesn't delete // it. Class unloading also walks the previous versions and might try to // delete it, so this class is used by class unloading also. -MetadataOnStackMark::MetadataOnStackMark(bool has_redefined_a_class) { +MetadataOnStackMark::MetadataOnStackMark(bool visit_code_cache) { assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); + assert(_used_buffers == NULL, "sanity check"); NOT_PRODUCT(_is_active = true;) - if (_marked_objects == NULL) { - _marked_objects = new (ResourceObj::C_HEAP, mtClass) GrowableArray<Metadata*>(1000, true); - } Threads::metadata_do(Metadata::mark_on_stack); - if (has_redefined_a_class) { + if (visit_code_cache) { CodeCache::alive_nmethods_do(nmethod::mark_on_stack); } CompileBroker::mark_on_stack(); @@ -62,15 +60,93 @@ // Unmark everything that was marked. Can't do the same walk because // redefine classes messes up the code cache so the set of methods // might not be the same. - for (int i = 0; i< _marked_objects->length(); i++) { - _marked_objects->at(i)->set_on_stack(false); + + retire_buffer_for_thread(Thread::current()); + + MetadataOnStackBuffer* buffer = const_cast<MetadataOnStackBuffer* >(_used_buffers); + while (buffer != NULL) { + // Clear on stack state for all metadata. + size_t size = buffer->size(); + for (size_t i = 0; i < size; i++) { + Metadata* md = buffer->at(i); + md->set_on_stack(false); + } + + MetadataOnStackBuffer* next = buffer->next_used(); + + // Move the buffer to the free list. + buffer->clear(); + buffer->set_next_used(NULL); + buffer->set_next_free(const_cast<MetadataOnStackBuffer*>(_free_buffers)); + _free_buffers = buffer; + + // Step to next used buffer. + buffer = next; } - _marked_objects->clear(); // reuse growable array for next time. + + _used_buffers = NULL; + NOT_PRODUCT(_is_active = false;) } +void MetadataOnStackMark::retire_buffer(MetadataOnStackBuffer* buffer) { + if (buffer == NULL) { + return; + } + + MetadataOnStackBuffer* old_head; + + do { + old_head = const_cast<MetadataOnStackBuffer*>(_used_buffers); + buffer->set_next_used(old_head); + } while (Atomic::cmpxchg_ptr(buffer, &_used_buffers, old_head) != old_head); +} + +void MetadataOnStackMark::retire_buffer_for_thread(Thread* thread) { + retire_buffer(thread->metadata_on_stack_buffer()); + thread->set_metadata_on_stack_buffer(NULL); +} + +bool MetadataOnStackMark::has_buffer_for_thread(Thread* thread) { + return thread->metadata_on_stack_buffer() != NULL; +} + +MetadataOnStackBuffer* MetadataOnStackMark::allocate_buffer() { + MetadataOnStackBuffer* allocated; + MetadataOnStackBuffer* new_head; + + do { + allocated = const_cast<MetadataOnStackBuffer*>(_free_buffers); + if (allocated == NULL) { + break; + } + new_head = allocated->next_free(); + } while (Atomic::cmpxchg_ptr(new_head, &_free_buffers, allocated) != allocated); + + if (allocated == NULL) { + allocated = new MetadataOnStackBuffer(); + } + + assert(!allocated->is_full(), err_msg("Should not be full: " PTR_FORMAT, p2i(allocated))); + + return allocated; +} + // Record which objects are marked so we can unmark the same objects. -void MetadataOnStackMark::record(Metadata* m) { +void MetadataOnStackMark::record(Metadata* m, Thread* thread) { assert(_is_active, "metadata on stack marking is active"); - _marked_objects->push(m); + + MetadataOnStackBuffer* buffer = thread->metadata_on_stack_buffer(); + + if (buffer != NULL && buffer->is_full()) { + retire_buffer(buffer); + buffer = NULL; + } + + if (buffer == NULL) { + buffer = allocate_buffer(); + thread->set_metadata_on_stack_buffer(buffer); + } + + buffer->push(m); }
--- a/hotspot/src/share/vm/classfile/metadataOnStackMark.hpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/classfile/metadataOnStackMark.hpp Wed Jul 05 20:05:54 2017 +0200 @@ -26,9 +26,12 @@ #define SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP #include "memory/allocation.hpp" +#include "utilities/chunkedList.hpp" class Metadata; +typedef ChunkedList<Metadata*, mtInternal> MetadataOnStackBuffer; + // Helper class to mark and unmark metadata used on the stack as either handles // or executing methods, so that it can't be deleted during class redefinition // and class unloading. @@ -36,10 +39,20 @@ // metadata during parsing, relocated methods, and methods in backtraces. class MetadataOnStackMark : public StackObj { NOT_PRODUCT(static bool _is_active;) + + static volatile MetadataOnStackBuffer* _used_buffers; + static volatile MetadataOnStackBuffer* _free_buffers; + + static MetadataOnStackBuffer* allocate_buffer(); + static void retire_buffer(MetadataOnStackBuffer* buffer); + public: - MetadataOnStackMark(bool has_redefined_a_class); - ~MetadataOnStackMark(); - static void record(Metadata* m); + MetadataOnStackMark(bool visit_code_cache); + ~MetadataOnStackMark(); + + static void record(Metadata* m, Thread* thread); + static void retire_buffer_for_thread(Thread* thread); + static bool has_buffer_for_thread(Thread* thread); }; #endif // SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -1690,9 +1690,9 @@ // Assumes classes in the SystemDictionary are only unloaded at a safepoint // Note: anonymous classes are not in the SD. -bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive) { +bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive, bool clean_alive) { // First, mark for unload all ClassLoaderData referencing a dead class loader. - bool unloading_occurred = ClassLoaderDataGraph::do_unloading(is_alive); + bool unloading_occurred = ClassLoaderDataGraph::do_unloading(is_alive, clean_alive); if (unloading_occurred) { dictionary()->do_unloading(); constraints()->purge_loader_constraints();
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Wed Jul 05 20:05:54 2017 +0200 @@ -334,7 +334,7 @@ // Unload (that is, break root links to) all unmarked classes and // loaders. Returns "true" iff something was unloaded. - static bool do_unloading(BoolObjectClosure* is_alive); + static bool do_unloading(BoolObjectClosure* is_alive, bool clean_alive = true); // Used by DumpSharedSpaces only to remove classes that failed verification static void remove_classes_in_error_state();
--- a/hotspot/src/share/vm/code/nmethod.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/code/nmethod.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -1700,11 +1700,17 @@ set_unload_reported(); } -void static clean_ic_if_metadata_is_dead(CompiledIC *ic, BoolObjectClosure *is_alive) { +void static clean_ic_if_metadata_is_dead(CompiledIC *ic, BoolObjectClosure *is_alive, bool mark_on_stack) { if (ic->is_icholder_call()) { // The only exception is compiledICHolder oops which may // yet be marked below. (We check this further below). CompiledICHolder* cichk_oop = ic->cached_icholder(); + + if (mark_on_stack) { + Metadata::mark_on_stack(cichk_oop->holder_method()); + Metadata::mark_on_stack(cichk_oop->holder_klass()); + } + if (cichk_oop->holder_method()->method_holder()->is_loader_alive(is_alive) && cichk_oop->holder_klass()->is_loader_alive(is_alive)) { return; @@ -1712,6 +1718,10 @@ } else { Metadata* ic_oop = ic->cached_metadata(); if (ic_oop != NULL) { + if (mark_on_stack) { + Metadata::mark_on_stack(ic_oop); + } + if (ic_oop->is_klass()) { if (((Klass*)ic_oop)->is_loader_alive(is_alive)) { return; @@ -1772,7 +1782,7 @@ while(iter.next()) { if (iter.type() == relocInfo::virtual_call_type) { CompiledIC *ic = CompiledIC_at(&iter); - clean_ic_if_metadata_is_dead(ic, is_alive); + clean_ic_if_metadata_is_dead(ic, is_alive, false); } } } @@ -1840,6 +1850,53 @@ return clean_if_nmethod_is_unloaded(csc, csc->destination(), is_alive, from); } +bool nmethod::unload_if_dead_at(RelocIterator* iter_at_oop, BoolObjectClosure *is_alive, bool unloading_occurred) { + assert(iter_at_oop->type() == relocInfo::oop_type, "Wrong relocation type"); + + oop_Relocation* r = iter_at_oop->oop_reloc(); + // Traverse those oops directly embedded in the code. + // Other oops (oop_index>0) are seen as part of scopes_oops. + assert(1 == (r->oop_is_immediate()) + + (r->oop_addr() >= oops_begin() && r->oop_addr() < oops_end()), + "oop must be found in exactly one place"); + if (r->oop_is_immediate() && r->oop_value() != NULL) { + // Unload this nmethod if the oop is dead. + if (can_unload(is_alive, r->oop_addr(), unloading_occurred)) { + return true;; + } + } + + return false; +} + +void nmethod::mark_metadata_on_stack_at(RelocIterator* iter_at_metadata) { + assert(iter_at_metadata->type() == relocInfo::metadata_type, "Wrong relocation type"); + + metadata_Relocation* r = iter_at_metadata->metadata_reloc(); + // In this metadata, we must only follow those metadatas directly embedded in + // the code. Other metadatas (oop_index>0) are seen as part of + // the metadata section below. + assert(1 == (r->metadata_is_immediate()) + + (r->metadata_addr() >= metadata_begin() && r->metadata_addr() < metadata_end()), + "metadata must be found in exactly one place"); + if (r->metadata_is_immediate() && r->metadata_value() != NULL) { + Metadata* md = r->metadata_value(); + if (md != _method) Metadata::mark_on_stack(md); + } +} + +void nmethod::mark_metadata_on_stack_non_relocs() { + // Visit the metadata section + for (Metadata** p = metadata_begin(); p < metadata_end(); p++) { + if (*p == Universe::non_oop_word() || *p == NULL) continue; // skip non-oops + Metadata* md = *p; + Metadata::mark_on_stack(md); + } + + // Visit metadata not embedded in the other places. + if (_method != NULL) Metadata::mark_on_stack(_method); +} + bool nmethod::do_unloading_parallel(BoolObjectClosure* is_alive, bool unloading_occurred) { ResourceMark rm; @@ -1869,6 +1926,11 @@ unloading_occurred = true; } + // When class redefinition is used all metadata in the CodeCache has to be recorded, + // so that unused "previous versions" can be purged. Since walking the CodeCache can + // be expensive, the "mark on stack" is piggy-backed on this parallel unloading code. + bool mark_metadata_on_stack = a_class_was_redefined; + // Exception cache clean_exception_cache(is_alive); @@ -1884,7 +1946,7 @@ if (unloading_occurred) { // If class unloading occurred we first iterate over all inline caches and // clear ICs where the cached oop is referring to an unloaded klass or method. - clean_ic_if_metadata_is_dead(CompiledIC_at(&iter), is_alive); + clean_ic_if_metadata_is_dead(CompiledIC_at(&iter), is_alive, mark_metadata_on_stack); } postponed |= clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this); @@ -1900,24 +1962,21 @@ case relocInfo::oop_type: if (!is_unloaded) { - // Unload check - oop_Relocation* r = iter.oop_reloc(); - // Traverse those oops directly embedded in the code. - // Other oops (oop_index>0) are seen as part of scopes_oops. - assert(1 == (r->oop_is_immediate()) + - (r->oop_addr() >= oops_begin() && r->oop_addr() < oops_end()), - "oop must be found in exactly one place"); - if (r->oop_is_immediate() && r->oop_value() != NULL) { - if (can_unload(is_alive, r->oop_addr(), unloading_occurred)) { - is_unloaded = true; - } - } + is_unloaded = unload_if_dead_at(&iter, is_alive, unloading_occurred); } break; + case relocInfo::metadata_type: + if (mark_metadata_on_stack) { + mark_metadata_on_stack_at(&iter); + } } } + if (mark_metadata_on_stack) { + mark_metadata_on_stack_non_relocs(); + } + if (is_unloaded) { return postponed; } @@ -2065,7 +2124,7 @@ while (iter.next()) { if (iter.type() == relocInfo::metadata_type ) { metadata_Relocation* r = iter.metadata_reloc(); - // In this lmetadata, we must only follow those metadatas directly embedded in + // In this metadata, we must only follow those metadatas directly embedded in // the code. Other metadatas (oop_index>0) are seen as part of // the metadata section below. assert(1 == (r->metadata_is_immediate()) + @@ -2099,7 +2158,7 @@ f(md); } - // Call function Method*, not embedded in these other places. + // Visit metadata not embedded in the other places. if (_method != NULL) f(_method); }
--- a/hotspot/src/share/vm/code/nmethod.hpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/code/nmethod.hpp Wed Jul 05 20:05:54 2017 +0200 @@ -615,9 +615,16 @@ // The parallel versions are used by G1. bool do_unloading_parallel(BoolObjectClosure* is_alive, bool unloading_occurred); void do_unloading_parallel_postponed(BoolObjectClosure* is_alive, bool unloading_occurred); + + private: // Unload a nmethod if the *root object is dead. bool can_unload(BoolObjectClosure* is_alive, oop* root, bool unloading_occurred); + bool unload_if_dead_at(RelocIterator *iter_at_oop, BoolObjectClosure* is_alive, bool unloading_occurred); + void mark_metadata_on_stack_at(RelocIterator* iter_at_metadata); + void mark_metadata_on_stack_non_relocs(); + + public: void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f); void oops_do(OopClosure* f) { oops_do(f, false); }
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/adaptiveFreeList.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/adaptiveFreeList.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -64,23 +64,6 @@ set_hint(hint); } -#ifndef PRODUCT -template <class Chunk> -void AdaptiveFreeList<Chunk>::assert_proper_lock_protection_work() const { - assert(protecting_lock() != NULL, "Don't call this directly"); - assert(ParallelGCThreads > 0, "Don't call this directly"); - Thread* thr = Thread::current(); - if (thr->is_VM_thread() || thr->is_ConcurrentGC_thread()) { - // assert that we are holding the freelist lock - } else if (thr->is_GC_task_thread()) { - assert(protecting_lock()->owned_by_self(), "FreeList RACE DETECTED"); - } else if (thr->is_Java_thread()) { - assert(!SafepointSynchronize::is_at_safepoint(), "Should not be executing"); - } else { - ShouldNotReachHere(); // unaccounted thread type? - } -} -#endif template <class Chunk> void AdaptiveFreeList<Chunk>::init_statistics(bool split_birth) { _allocation_stats.initialize(split_birth);
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/adaptiveFreeList.hpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/adaptiveFreeList.hpp Wed Jul 05 20:05:54 2017 +0200 @@ -81,8 +81,6 @@ // Reset the head, tail, hint, and count of a free list. void reset(size_t hint); - void assert_proper_lock_protection_work() const PRODUCT_RETURN; - void print_on(outputStream* st, const char* c = NULL) const; size_t hint() const {
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -149,18 +149,15 @@ check_free_list_consistency(); // Initialize locks for parallel case. - - if (CollectedHeap::use_parallel_gc_threads()) { - for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { - _indexedFreeListParLocks[i] = new Mutex(Mutex::leaf - 1, // == ExpandHeap_lock - 1 - "a freelist par lock", - true); - DEBUG_ONLY( - _indexedFreeList[i].set_protecting_lock(_indexedFreeListParLocks[i]); - ) - } - _dictionary->set_par_lock(&_parDictionaryAllocLock); + for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { + _indexedFreeListParLocks[i] = new Mutex(Mutex::leaf - 1, // == ExpandHeap_lock - 1 + "a freelist par lock", + true); + DEBUG_ONLY( + _indexedFreeList[i].set_protecting_lock(_indexedFreeListParLocks[i]); + ) } + _dictionary->set_par_lock(&_parDictionaryAllocLock); } // Like CompactibleSpace forward() but always calls cross_threshold() to @@ -622,17 +619,11 @@ // Mark the boundary of the new block in BOT _bt.mark_block(prevEnd, value); // put it all in the linAB - if (ParallelGCThreads == 0) { - _smallLinearAllocBlock._ptr = prevEnd; - _smallLinearAllocBlock._word_size = newFcSize; - repairLinearAllocBlock(&_smallLinearAllocBlock); - } else { // ParallelGCThreads > 0 - MutexLockerEx x(parDictionaryAllocLock(), - Mutex::_no_safepoint_check_flag); - _smallLinearAllocBlock._ptr = prevEnd; - _smallLinearAllocBlock._word_size = newFcSize; - repairLinearAllocBlock(&_smallLinearAllocBlock); - } + MutexLockerEx x(parDictionaryAllocLock(), + Mutex::_no_safepoint_check_flag); + _smallLinearAllocBlock._ptr = prevEnd; + _smallLinearAllocBlock._word_size = newFcSize; + repairLinearAllocBlock(&_smallLinearAllocBlock); // Births of chunks put into a LinAB are not recorded. Births // of chunks as they are allocated out of a LinAB are. } else { @@ -1740,10 +1731,7 @@ assert(chunk != NULL && is_in_reserved(chunk), "Not in this space!"); // One of the parallel gc task threads may be here // whilst others are allocating. - Mutex* lock = NULL; - if (ParallelGCThreads != 0) { - lock = &_parDictionaryAllocLock; - } + Mutex* lock = &_parDictionaryAllocLock; FreeChunk* ec; { MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag); @@ -1760,7 +1748,7 @@ } ec->set_size(size); debug_only(ec->mangleFreed(size)); - if (size < SmallForDictionary && ParallelGCThreads != 0) { + if (size < SmallForDictionary) { lock = _indexedFreeListParLocks[size]; } MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag);
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -887,10 +887,8 @@ // along with all the other pointers into the heap but // compaction is expected to be a rare event with // a heap using cms so don't do it without seeing the need. - if (CollectedHeap::use_parallel_gc_threads()) { - for (uint i = 0; i < ParallelGCThreads; i++) { - _par_gc_thread_states[i]->promo.reset(); - } + for (uint i = 0; i < ParallelGCThreads; i++) { + _par_gc_thread_states[i]->promo.reset(); } } @@ -2804,10 +2802,8 @@ collector()->gc_epilogue(full); // Also reset promotion tracking in par gc thread states. - if (CollectedHeap::use_parallel_gc_threads()) { - for (uint i = 0; i < ParallelGCThreads; i++) { - _par_gc_thread_states[i]->promo.stopTrackingPromotions(i); - } + for (uint i = 0; i < ParallelGCThreads; i++) { + _par_gc_thread_states[i]->promo.stopTrackingPromotions(i); } }
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/metadataOnStackMark.hpp" #include "classfile/symbolTable.hpp" #include "code/codeCache.hpp" #include "gc_implementation/g1/concurrentMark.inline.hpp" @@ -611,74 +612,64 @@ ConcGCThreads, ParallelGCThreads); return; } - if (ParallelGCThreads == 0) { - // if we are not running with any parallel GC threads we will not - // spawn any marking threads either - _parallel_marking_threads = 0; - _max_parallel_marking_threads = 0; - _sleep_factor = 0.0; - _marking_task_overhead = 1.0; + if (!FLAG_IS_DEFAULT(ConcGCThreads) && ConcGCThreads > 0) { + // Note: ConcGCThreads has precedence over G1MarkingOverheadPercent + // if both are set + _sleep_factor = 0.0; + _marking_task_overhead = 1.0; + } else if (G1MarkingOverheadPercent > 0) { + // We will calculate the number of parallel marking threads based + // on a target overhead with respect to the soft real-time goal + double marking_overhead = (double) G1MarkingOverheadPercent / 100.0; + double overall_cm_overhead = + (double) MaxGCPauseMillis * marking_overhead / + (double) GCPauseIntervalMillis; + double cpu_ratio = 1.0 / (double) os::processor_count(); + double marking_thread_num = ceil(overall_cm_overhead / cpu_ratio); + double marking_task_overhead = + overall_cm_overhead / marking_thread_num * + (double) os::processor_count(); + double sleep_factor = + (1.0 - marking_task_overhead) / marking_task_overhead; + + FLAG_SET_ERGO(uintx, ConcGCThreads, (uint) marking_thread_num); + _sleep_factor = sleep_factor; + _marking_task_overhead = marking_task_overhead; } else { - if (!FLAG_IS_DEFAULT(ConcGCThreads) && ConcGCThreads > 0) { - // Note: ConcGCThreads has precedence over G1MarkingOverheadPercent - // if both are set - _sleep_factor = 0.0; - _marking_task_overhead = 1.0; - } else if (G1MarkingOverheadPercent > 0) { - // We will calculate the number of parallel marking threads based - // on a target overhead with respect to the soft real-time goal - double marking_overhead = (double) G1MarkingOverheadPercent / 100.0; - double overall_cm_overhead = - (double) MaxGCPauseMillis * marking_overhead / - (double) GCPauseIntervalMillis; - double cpu_ratio = 1.0 / (double) os::processor_count(); - double marking_thread_num = ceil(overall_cm_overhead / cpu_ratio); - double marking_task_overhead = - overall_cm_overhead / marking_thread_num * - (double) os::processor_count(); - double sleep_factor = - (1.0 - marking_task_overhead) / marking_task_overhead; - - FLAG_SET_ERGO(uintx, ConcGCThreads, (uint) marking_thread_num); - _sleep_factor = sleep_factor; - _marking_task_overhead = marking_task_overhead; - } else { - // Calculate the number of parallel marking threads by scaling - // the number of parallel GC threads. - uint marking_thread_num = scale_parallel_threads((uint) ParallelGCThreads); - FLAG_SET_ERGO(uintx, ConcGCThreads, marking_thread_num); - _sleep_factor = 0.0; - _marking_task_overhead = 1.0; - } - - assert(ConcGCThreads > 0, "Should have been set"); - _parallel_marking_threads = (uint) ConcGCThreads; - _max_parallel_marking_threads = _parallel_marking_threads; - - if (parallel_marking_threads() > 1) { - _cleanup_task_overhead = 1.0; - } else { - _cleanup_task_overhead = marking_task_overhead(); - } - _cleanup_sleep_factor = - (1.0 - cleanup_task_overhead()) / cleanup_task_overhead(); + // Calculate the number of parallel marking threads by scaling + // the number of parallel GC threads. + uint marking_thread_num = scale_parallel_threads((uint) ParallelGCThreads); + FLAG_SET_ERGO(uintx, ConcGCThreads, marking_thread_num); + _sleep_factor = 0.0; + _marking_task_overhead = 1.0; + } + + assert(ConcGCThreads > 0, "Should have been set"); + _parallel_marking_threads = (uint) ConcGCThreads; + _max_parallel_marking_threads = _parallel_marking_threads; + + if (parallel_marking_threads() > 1) { + _cleanup_task_overhead = 1.0; + } else { + _cleanup_task_overhead = marking_task_overhead(); + } + _cleanup_sleep_factor = + (1.0 - cleanup_task_overhead()) / cleanup_task_overhead(); #if 0 - gclog_or_tty->print_cr("Marking Threads %d", parallel_marking_threads()); - gclog_or_tty->print_cr("CM Marking Task Overhead %1.4lf", marking_task_overhead()); - gclog_or_tty->print_cr("CM Sleep Factor %1.4lf", sleep_factor()); - gclog_or_tty->print_cr("CL Marking Task Overhead %1.4lf", cleanup_task_overhead()); - gclog_or_tty->print_cr("CL Sleep Factor %1.4lf", cleanup_sleep_factor()); + gclog_or_tty->print_cr("Marking Threads %d", parallel_marking_threads()); + gclog_or_tty->print_cr("CM Marking Task Overhead %1.4lf", marking_task_overhead()); + gclog_or_tty->print_cr("CM Sleep Factor %1.4lf", sleep_factor()); + gclog_or_tty->print_cr("CL Marking Task Overhead %1.4lf", cleanup_task_overhead()); + gclog_or_tty->print_cr("CL Sleep Factor %1.4lf", cleanup_sleep_factor()); #endif - guarantee(parallel_marking_threads() > 0, "peace of mind"); - _parallel_workers = new FlexibleWorkGang("G1 Parallel Marking Threads", - _max_parallel_marking_threads, false, true); - if (_parallel_workers == NULL) { - vm_exit_during_initialization("Failed necessary allocation."); - } else { - _parallel_workers->initialize_workers(); - } + _parallel_workers = new FlexibleWorkGang("G1 Parallel Marking Threads", + _max_parallel_marking_threads, false, true); + if (_parallel_workers == NULL) { + vm_exit_during_initialization("Failed necessary allocation."); + } else { + _parallel_workers->initialize_workers(); } if (FLAG_IS_DEFAULT(MarkStackSize)) { @@ -1166,29 +1157,23 @@ // Calculates the number of active workers for a concurrent // phase. uint ConcurrentMark::calc_parallel_marking_threads() { - if (G1CollectedHeap::use_parallel_gc_threads()) { - uint n_conc_workers = 0; - if (!UseDynamicNumberOfGCThreads || - (!FLAG_IS_DEFAULT(ConcGCThreads) && - !ForceDynamicNumberOfGCThreads)) { - n_conc_workers = max_parallel_marking_threads(); - } else { - n_conc_workers = - AdaptiveSizePolicy::calc_default_active_workers( - max_parallel_marking_threads(), - 1, /* Minimum workers */ - parallel_marking_threads(), - Threads::number_of_non_daemon_threads()); - // Don't scale down "n_conc_workers" by scale_parallel_threads() because - // that scaling has already gone into "_max_parallel_marking_threads". - } - assert(n_conc_workers > 0, "Always need at least 1"); - return n_conc_workers; + uint n_conc_workers = 0; + if (!UseDynamicNumberOfGCThreads || + (!FLAG_IS_DEFAULT(ConcGCThreads) && + !ForceDynamicNumberOfGCThreads)) { + n_conc_workers = max_parallel_marking_threads(); + } else { + n_conc_workers = + AdaptiveSizePolicy::calc_default_active_workers( + max_parallel_marking_threads(), + 1, /* Minimum workers */ + parallel_marking_threads(), + Threads::number_of_non_daemon_threads()); + // Don't scale down "n_conc_workers" by scale_parallel_threads() because + // that scaling has already gone into "_max_parallel_marking_threads". } - // If we are not running with any parallel GC threads we will not - // have spawned any marking threads either. Hence the number of - // concurrent workers should be 0. - return 0; + assert(n_conc_workers > 0, "Always need at least 1"); + return n_conc_workers; } void ConcurrentMark::scanRootRegion(HeapRegion* hr, uint worker_id) { @@ -1243,12 +1228,8 @@ uint active_workers = MAX2(1U, parallel_marking_threads()); CMRootRegionScanTask task(this); - if (use_parallel_marking_threads()) { - _parallel_workers->set_active_workers((int) active_workers); - _parallel_workers->run_task(&task); - } else { - task.work(0); - } + _parallel_workers->set_active_workers(active_workers); + _parallel_workers->run_task(&task); // It's possible that has_aborted() is true here without actually // aborting the survivor scan earlier. This is OK as it's @@ -1279,15 +1260,11 @@ set_concurrency_and_phase(active_workers, true /* concurrent */); CMConcurrentMarkingTask markingTask(this, cmThread()); - if (use_parallel_marking_threads()) { - _parallel_workers->set_active_workers((int)active_workers); - // Don't set _n_par_threads because it affects MT in process_roots() - // and the decisions on that MT processing is made elsewhere. - assert(_parallel_workers->active_workers() > 0, "Should have been set"); - _parallel_workers->run_task(&markingTask); - } else { - markingTask.work(0); - } + _parallel_workers->set_active_workers(active_workers); + // Don't set _n_par_threads because it affects MT in process_roots() + // and the decisions on that MT processing is made elsewhere. + assert(_parallel_workers->active_workers() > 0, "Should have been set"); + _parallel_workers->run_task(&markingTask); print_stats(); } @@ -1714,11 +1691,7 @@ _expected_card_bm, _verbose); - if (G1CollectedHeap::use_parallel_gc_threads()) { - _g1h->heap_region_par_iterate(&verify_cl, worker_id, &_hrclaimer); - } else { - _g1h->heap_region_iterate(&verify_cl); - } + _g1h->heap_region_par_iterate(&verify_cl, worker_id, &_hrclaimer); Atomic::add(verify_cl.failures(), &_failures); } @@ -1821,11 +1794,7 @@ _actual_region_bm, _actual_card_bm); - if (G1CollectedHeap::use_parallel_gc_threads()) { - _g1h->heap_region_par_iterate(&final_update_cl, worker_id, &_hrclaimer); - } else { - _g1h->heap_region_iterate(&final_update_cl); - } + _g1h->heap_region_par_iterate(&final_update_cl, worker_id, &_hrclaimer); } }; @@ -1922,11 +1891,7 @@ HRRSCleanupTask hrrs_cleanup_task; G1NoteEndOfConcMarkClosure g1_note_end(_g1h, &local_cleanup_list, &hrrs_cleanup_task); - if (G1CollectedHeap::use_parallel_gc_threads()) { - _g1h->heap_region_par_iterate(&g1_note_end, worker_id, &_hrclaimer); - } else { - _g1h->heap_region_iterate(&g1_note_end); - } + _g1h->heap_region_par_iterate(&g1_note_end, worker_id, &_hrclaimer); assert(g1_note_end.complete(), "Shouldn't have yielded!"); // Now update the lists @@ -1977,11 +1942,7 @@ } void work(uint worker_id) { - if (G1CollectedHeap::use_parallel_gc_threads()) { - _g1rs->scrub_par(_region_bm, _card_bm, worker_id, &_hrclaimer); - } else { - _g1rs->scrub(_region_bm, _card_bm); - } + _g1rs->scrub(_region_bm, _card_bm, worker_id, &_hrclaimer); } }; @@ -2020,18 +1981,13 @@ // Do counting once more with the world stopped for good measure. G1ParFinalCountTask g1_par_count_task(g1h, &_region_bm, &_card_bm); - if (G1CollectedHeap::use_parallel_gc_threads()) { - g1h->set_par_threads(); - n_workers = g1h->n_par_threads(); - assert(g1h->n_par_threads() == n_workers, - "Should not have been reset"); - g1h->workers()->run_task(&g1_par_count_task); - // Done with the parallel phase so reset to 0. - g1h->set_par_threads(0); - } else { - n_workers = 1; - g1_par_count_task.work(0); - } + g1h->set_par_threads(); + n_workers = g1h->n_par_threads(); + assert(g1h->n_par_threads() == n_workers, + "Should not have been reset"); + g1h->workers()->run_task(&g1_par_count_task); + // Done with the parallel phase so reset to 0. + g1h->set_par_threads(0); if (VerifyDuringGC) { // Verify that the counting data accumulated during marking matches @@ -2047,14 +2003,10 @@ &expected_region_bm, &expected_card_bm); - if (G1CollectedHeap::use_parallel_gc_threads()) { - g1h->set_par_threads((int)n_workers); - g1h->workers()->run_task(&g1_par_verify_task); - // Done with the parallel phase so reset to 0. - g1h->set_par_threads(0); - } else { - g1_par_verify_task.work(0); - } + g1h->set_par_threads((int)n_workers); + g1h->workers()->run_task(&g1_par_verify_task); + // Done with the parallel phase so reset to 0. + g1h->set_par_threads(0); guarantee(g1_par_verify_task.failures() == 0, "Unexpected accounting failures"); } @@ -2078,13 +2030,9 @@ // Note end of marking in all heap regions. G1ParNoteEndTask g1_par_note_end_task(g1h, &_cleanup_list, n_workers); - if (G1CollectedHeap::use_parallel_gc_threads()) { - g1h->set_par_threads((int)n_workers); - g1h->workers()->run_task(&g1_par_note_end_task); - g1h->set_par_threads(0); - } else { - g1_par_note_end_task.work(0); - } + g1h->set_par_threads((int)n_workers); + g1h->workers()->run_task(&g1_par_note_end_task); + g1h->set_par_threads(0); g1h->check_gc_time_stamps(); if (!cleanup_list_is_empty()) { @@ -2099,13 +2047,9 @@ if (G1ScrubRemSets) { double rs_scrub_start = os::elapsedTime(); G1ParScrubRemSetTask g1_par_scrub_rs_task(g1h, &_region_bm, &_card_bm, n_workers); - if (G1CollectedHeap::use_parallel_gc_threads()) { - g1h->set_par_threads((int)n_workers); - g1h->workers()->run_task(&g1_par_scrub_rs_task); - g1h->set_par_threads(0); - } else { - g1_par_scrub_rs_task.work(0); - } + g1h->set_par_threads((int)n_workers); + g1h->workers()->run_task(&g1_par_scrub_rs_task); + g1h->set_par_threads(0); double rs_scrub_end = os::elapsedTime(); double this_rs_scrub_time = (rs_scrub_end - rs_scrub_start); @@ -2502,7 +2446,7 @@ // is not multi-threaded we use the current (VMThread) thread, // otherwise we use the work gang from the G1CollectedHeap and // we utilize all the worker threads we can. - bool processing_is_mt = rp->processing_is_mt() && g1h->workers() != NULL; + bool processing_is_mt = rp->processing_is_mt(); uint active_workers = (processing_is_mt ? g1h->workers()->active_workers() : 1U); active_workers = MAX2(MIN2(active_workers, _max_worker_id), 1U); @@ -2564,17 +2508,27 @@ G1CMTraceTime trace("Unloading", G1Log::finer()); if (ClassUnloadingWithConcurrentMark) { + // Cleaning of klasses depends on correct information from MetadataMarkOnStack. The CodeCache::mark_on_stack + // part is too slow to be done serially, so it is handled during the weakRefsWorkParallelPart phase. + // Defer the cleaning until we have complete on_stack data. + MetadataOnStackMark md_on_stack(false /* Don't visit the code cache at this point */); + bool purged_classes; { G1CMTraceTime trace("System Dictionary Unloading", G1Log::finest()); - purged_classes = SystemDictionary::do_unloading(&g1_is_alive); + purged_classes = SystemDictionary::do_unloading(&g1_is_alive, false /* Defer klass cleaning */); } { G1CMTraceTime trace("Parallel Unloading", G1Log::finest()); weakRefsWorkParallelPart(&g1_is_alive, purged_classes); } + + { + G1CMTraceTime trace("Deallocate Metadata", G1Log::finest()); + ClassLoaderDataGraph::free_deallocate_lists(); + } } if (G1StringDedup::is_enabled()) { @@ -2611,16 +2565,15 @@ G1CMOopClosure _cm_cl; MarkingCodeBlobClosure _code_cl; int _thread_parity; - bool _is_par; public: - G1RemarkThreadsClosure(G1CollectedHeap* g1h, CMTask* task, bool is_par) : + G1RemarkThreadsClosure(G1CollectedHeap* g1h, CMTask* task) : _cm_obj(task), _cm_cl(g1h, g1h->concurrent_mark(), task), _code_cl(&_cm_cl, !CodeBlobToOopClosure::FixRelocations), - _thread_parity(SharedHeap::heap()->strong_roots_parity()), _is_par(is_par) {} + _thread_parity(SharedHeap::heap()->strong_roots_parity()) {} void do_thread(Thread* thread) { if (thread->is_Java_thread()) { - if (thread->claim_oops_do(_is_par, _thread_parity)) { + if (thread->claim_oops_do(true, _thread_parity)) { JavaThread* jt = (JavaThread*)thread; // In theory it should not be neccessary to explicitly walk the nmethods to find roots for concurrent marking @@ -2634,7 +2587,7 @@ jt->satb_mark_queue().apply_closure_and_empty(&_cm_obj); } } else if (thread->is_VM_thread()) { - if (thread->claim_oops_do(_is_par, _thread_parity)) { + if (thread->claim_oops_do(true, _thread_parity)) { JavaThread::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(&_cm_obj); } } @@ -2644,7 +2597,6 @@ class CMRemarkTask: public AbstractGangTask { private: ConcurrentMark* _cm; - bool _is_serial; public: void work(uint worker_id) { // Since all available tasks are actually started, we should @@ -2656,14 +2608,14 @@ ResourceMark rm; HandleMark hm; - G1RemarkThreadsClosure threads_f(G1CollectedHeap::heap(), task, !_is_serial); + G1RemarkThreadsClosure threads_f(G1CollectedHeap::heap(), task); Threads::threads_do(&threads_f); } do { task->do_marking_step(1000000000.0 /* something very large */, true /* do_termination */, - _is_serial); + false /* is_serial */); } while (task->has_aborted() && !_cm->has_overflown()); // If we overflow, then we do not want to restart. We instead // want to abort remark and do concurrent marking again. @@ -2671,8 +2623,8 @@ } } - CMRemarkTask(ConcurrentMark* cm, int active_workers, bool is_serial) : - AbstractGangTask("Par Remark"), _cm(cm), _is_serial(is_serial) { + CMRemarkTask(ConcurrentMark* cm, int active_workers) : + AbstractGangTask("Par Remark"), _cm(cm) { _cm->terminator()->reset_for_reuse(active_workers); } }; @@ -2686,43 +2638,28 @@ g1h->ensure_parsability(false); - if (G1CollectedHeap::use_parallel_gc_threads()) { - G1CollectedHeap::StrongRootsScope srs(g1h); - // this is remark, so we'll use up all active threads - uint active_workers = g1h->workers()->active_workers(); - if (active_workers == 0) { - assert(active_workers > 0, "Should have been set earlier"); - active_workers = (uint) ParallelGCThreads; - g1h->workers()->set_active_workers(active_workers); - } - set_concurrency_and_phase(active_workers, false /* concurrent */); - // Leave _parallel_marking_threads at it's - // value originally calculated in the ConcurrentMark - // constructor and pass values of the active workers - // through the gang in the task. - - CMRemarkTask remarkTask(this, active_workers, false /* is_serial */); - // We will start all available threads, even if we decide that the - // active_workers will be fewer. The extra ones will just bail out - // immediately. - g1h->set_par_threads(active_workers); - g1h->workers()->run_task(&remarkTask); - g1h->set_par_threads(0); - } else { - G1CollectedHeap::StrongRootsScope srs(g1h); - uint active_workers = 1; - set_concurrency_and_phase(active_workers, false /* concurrent */); - - // Note - if there's no work gang then the VMThread will be - // the thread to execute the remark - serially. We have - // to pass true for the is_serial parameter so that - // CMTask::do_marking_step() doesn't enter the sync - // barriers in the event of an overflow. Doing so will - // cause an assert that the current thread is not a - // concurrent GC thread. - CMRemarkTask remarkTask(this, active_workers, true /* is_serial*/); - remarkTask.work(0); + G1CollectedHeap::StrongRootsScope srs(g1h); + // this is remark, so we'll use up all active threads + uint active_workers = g1h->workers()->active_workers(); + if (active_workers == 0) { + assert(active_workers > 0, "Should have been set earlier"); + active_workers = (uint) ParallelGCThreads; + g1h->workers()->set_active_workers(active_workers); } + set_concurrency_and_phase(active_workers, false /* concurrent */); + // Leave _parallel_marking_threads at it's + // value originally calculated in the ConcurrentMark + // constructor and pass values of the active workers + // through the gang in the task. + + CMRemarkTask remarkTask(this, active_workers); + // We will start all available threads, even if we decide that the + // active_workers will be fewer. The extra ones will just bail out + // immediately. + g1h->set_par_threads(active_workers); + g1h->workers()->run_task(&remarkTask); + g1h->set_par_threads(0); + SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); guarantee(has_overflown() || satb_mq_set.completed_buffers_num() == 0, @@ -3268,30 +3205,20 @@ void work(uint worker_id) { AggregateCountDataHRClosure cl(_g1h, _cm_card_bm, _max_worker_id); - if (G1CollectedHeap::use_parallel_gc_threads()) { - _g1h->heap_region_par_iterate(&cl, worker_id, &_hrclaimer); - } else { - _g1h->heap_region_iterate(&cl); - } + _g1h->heap_region_par_iterate(&cl, worker_id, &_hrclaimer); } }; void ConcurrentMark::aggregate_count_data() { - int n_workers = (G1CollectedHeap::use_parallel_gc_threads() ? - _g1h->workers()->active_workers() : - 1); + int n_workers = _g1h->workers()->active_workers(); G1AggregateCountDataTask g1_par_agg_task(_g1h, this, &_card_bm, _max_worker_id, n_workers); - if (G1CollectedHeap::use_parallel_gc_threads()) { - _g1h->set_par_threads(n_workers); - _g1h->workers()->run_task(&g1_par_agg_task); - _g1h->set_par_threads(0); - } else { - g1_par_agg_task.work(0); - } + _g1h->set_par_threads(n_workers); + _g1h->workers()->run_task(&g1_par_agg_task); + _g1h->set_par_threads(0); _g1h->allocation_context_stats().update_at_remark(); } @@ -3419,9 +3346,7 @@ } void ConcurrentMark::print_worker_threads_on(outputStream* st) const { - if (use_parallel_marking_threads()) { - _parallel_workers->print_worker_threads_on(st); - } + _parallel_workers->print_worker_threads_on(st); } void ConcurrentMark::print_on_error(outputStream* st) const { @@ -3942,32 +3867,17 @@ CMObjectClosure oc(this); SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); - if (G1CollectedHeap::use_parallel_gc_threads()) { - satb_mq_set.set_par_closure(_worker_id, &oc); - } else { - satb_mq_set.set_closure(&oc); - } + satb_mq_set.set_closure(_worker_id, &oc); // This keeps claiming and applying the closure to completed buffers // until we run out of buffers or we need to abort. - if (G1CollectedHeap::use_parallel_gc_threads()) { - while (!has_aborted() && - satb_mq_set.par_apply_closure_to_completed_buffer(_worker_id)) { - if (_cm->verbose_medium()) { - gclog_or_tty->print_cr("[%u] processed an SATB buffer", _worker_id); - } - statsOnly( ++_satb_buffers_processed ); - regular_clock_call(); + while (!has_aborted() && + satb_mq_set.apply_closure_to_completed_buffer(_worker_id)) { + if (_cm->verbose_medium()) { + gclog_or_tty->print_cr("[%u] processed an SATB buffer", _worker_id); } - } else { - while (!has_aborted() && - satb_mq_set.apply_closure_to_completed_buffer()) { - if (_cm->verbose_medium()) { - gclog_or_tty->print_cr("[%u] processed an SATB buffer", _worker_id); - } - statsOnly( ++_satb_buffers_processed ); - regular_clock_call(); - } + statsOnly( ++_satb_buffers_processed ); + regular_clock_call(); } _draining_satb_buffers = false; @@ -3976,11 +3886,7 @@ concurrent() || satb_mq_set.completed_buffers_num() == 0, "invariant"); - if (G1CollectedHeap::use_parallel_gc_threads()) { - satb_mq_set.set_par_closure(_worker_id, NULL); - } else { - satb_mq_set.set_closure(NULL); - } + satb_mq_set.set_closure(_worker_id, NULL); // again, this was a potentially expensive operation, decrease the // limits to get the regular clock call early
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Wed Jul 05 20:05:54 2017 +0200 @@ -519,15 +519,6 @@ double cleanup_sleep_factor() { return _cleanup_sleep_factor; } double cleanup_task_overhead() { return _cleanup_task_overhead;} - bool use_parallel_marking_threads() const { - assert(parallel_marking_threads() <= - max_parallel_marking_threads(), "sanity"); - assert((_parallel_workers == NULL && parallel_marking_threads() == 0) || - parallel_marking_threads() > 0, - "parallel workers not set up correctly"); - return _parallel_workers != NULL; - } - HeapWord* finger() { return _finger; } bool concurrent() { return _concurrent; } uint active_tasks() { return _active_tasks; }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -28,6 +28,7 @@ #endif #include "precompiled.hpp" +#include "classfile/metadataOnStackMark.hpp" #include "classfile/stringTable.hpp" #include "code/codeCache.hpp" #include "code/icBuffer.hpp" @@ -1438,36 +1439,31 @@ } // Rebuild remembered sets of all regions. - if (G1CollectedHeap::use_parallel_gc_threads()) { - uint n_workers = - AdaptiveSizePolicy::calc_active_workers(workers()->total_workers(), - workers()->active_workers(), - Threads::number_of_non_daemon_threads()); - assert(UseDynamicNumberOfGCThreads || - n_workers == workers()->total_workers(), - "If not dynamic should be using all the workers"); - workers()->set_active_workers(n_workers); - // Set parallel threads in the heap (_n_par_threads) only - // before a parallel phase and always reset it to 0 after - // the phase so that the number of parallel threads does - // no get carried forward to a serial phase where there - // may be code that is "possibly_parallel". - set_par_threads(n_workers); - - ParRebuildRSTask rebuild_rs_task(this); - assert(UseDynamicNumberOfGCThreads || - workers()->active_workers() == workers()->total_workers(), - "Unless dynamic should use total workers"); - // Use the most recent number of active workers - assert(workers()->active_workers() > 0, - "Active workers not properly set"); - set_par_threads(workers()->active_workers()); - workers()->run_task(&rebuild_rs_task); - set_par_threads(0); - } else { - RebuildRSOutOfRegionClosure rebuild_rs(this); - heap_region_iterate(&rebuild_rs); - } + uint n_workers = + AdaptiveSizePolicy::calc_active_workers(workers()->total_workers(), + workers()->active_workers(), + Threads::number_of_non_daemon_threads()); + assert(UseDynamicNumberOfGCThreads || + n_workers == workers()->total_workers(), + "If not dynamic should be using all the workers"); + workers()->set_active_workers(n_workers); + // Set parallel threads in the heap (_n_par_threads) only + // before a parallel phase and always reset it to 0 after + // the phase so that the number of parallel threads does + // no get carried forward to a serial phase where there + // may be code that is "possibly_parallel". + set_par_threads(n_workers); + + ParRebuildRSTask rebuild_rs_task(this); + assert(UseDynamicNumberOfGCThreads || + workers()->active_workers() == workers()->total_workers(), + "Unless dynamic should use total workers"); + // Use the most recent number of active workers + assert(workers()->active_workers() > 0, + "Active workers not properly set"); + set_par_threads(workers()->active_workers()); + workers()->run_task(&rebuild_rs_task); + set_par_threads(0); // Rebuild the strong code root lists for each region rebuild_strong_code_roots(); @@ -2482,6 +2478,7 @@ unsigned int gc_count_before; unsigned int old_marking_count_before; + unsigned int full_gc_count_before; bool retry_gc; do { @@ -2492,6 +2489,7 @@ // Read the GC count while holding the Heap_lock gc_count_before = total_collections(); + full_gc_count_before = total_full_collections(); old_marking_count_before = _old_marking_cycles_started; } @@ -2536,7 +2534,7 @@ VMThread::execute(&op); } else { // Schedule a Full GC. - VM_G1CollectFull op(gc_count_before, old_marking_count_before, cause); + VM_G1CollectFull op(gc_count_before, full_gc_count_before, cause); VMThread::execute(&op); } } @@ -2678,27 +2676,25 @@ // Then thread t will start at region floor ((t * n) / p) result = g1_policy()->collection_set(); - if (G1CollectedHeap::use_parallel_gc_threads()) { - uint cs_size = g1_policy()->cset_region_length(); - uint active_workers = workers()->active_workers(); - assert(UseDynamicNumberOfGCThreads || - active_workers == workers()->total_workers(), - "Unless dynamic should use total workers"); - - uint end_ind = (cs_size * worker_i) / active_workers; - uint start_ind = 0; - - if (worker_i > 0 && - _worker_cset_start_region_time_stamp[worker_i - 1] == gc_time_stamp) { - // Previous workers starting region is valid - // so let's iterate from there - start_ind = (cs_size * (worker_i - 1)) / active_workers; - result = _worker_cset_start_region[worker_i - 1]; - } - - for (uint i = start_ind; i < end_ind; i++) { - result = result->next_in_collection_set(); - } + uint cs_size = g1_policy()->cset_region_length(); + uint active_workers = workers()->active_workers(); + assert(UseDynamicNumberOfGCThreads || + active_workers == workers()->total_workers(), + "Unless dynamic should use total workers"); + + uint end_ind = (cs_size * worker_i) / active_workers; + uint start_ind = 0; + + if (worker_i > 0 && + _worker_cset_start_region_time_stamp[worker_i - 1] == gc_time_stamp) { + // Previous workers starting region is valid + // so let's iterate from there + start_ind = (cs_size * (worker_i - 1)) / active_workers; + result = _worker_cset_start_region[worker_i - 1]; + } + + for (uint i = start_ind; i < end_ind; i++) { + result = result->next_in_collection_set(); } // Note: the calculated starting heap region may be NULL @@ -3373,9 +3369,7 @@ } void G1CollectedHeap::print_gc_threads_on(outputStream* st) const { - if (G1CollectedHeap::use_parallel_gc_threads()) { - workers()->print_worker_threads_on(st); - } + workers()->print_worker_threads_on(st); _cmThread->print_on(st); st->cr(); _cm->print_worker_threads_on(st); @@ -3386,9 +3380,7 @@ } void G1CollectedHeap::gc_threads_do(ThreadClosure* tc) const { - if (G1CollectedHeap::use_parallel_gc_threads()) { - workers()->threads_do(tc); - } + workers()->threads_do(tc); tc->do_thread(_cmThread); _cg1r->threads_do(tc); if (G1StringDedup::is_enabled()) { @@ -3683,7 +3675,7 @@ print_taskqueue_stats_hdr(st); TaskQueueStats totals; - const int n = workers() != NULL ? workers()->total_workers() : 1; + const int n = workers()->total_workers(); for (int i = 0; i < n; ++i) { st->print("%3d ", i); task_queue(i)->stats.print(st); st->cr(); totals += task_queue(i)->stats; @@ -3694,7 +3686,7 @@ } void G1CollectedHeap::reset_taskqueue_stats() { - const int n = workers() != NULL ? workers()->total_workers() : 1; + const int n = workers()->total_workers(); for (int i = 0; i < n; ++i) { task_queue(i)->stats.reset(); } @@ -3792,8 +3784,7 @@ TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty); - int active_workers = (G1CollectedHeap::use_parallel_gc_threads() ? - workers()->active_workers() : 1); + int active_workers = workers()->active_workers(); double pause_start_sec = os::elapsedTime(); g1_policy()->phase_times()->note_gc_start(active_workers); log_gc_header(); @@ -4787,12 +4778,10 @@ int _symbols_processed; int _symbols_removed; - bool _do_in_parallel; public: G1StringSymbolTableUnlinkTask(BoolObjectClosure* is_alive, bool process_strings, bool process_symbols) : AbstractGangTask("String/Symbol Unlinking"), _is_alive(is_alive), - _do_in_parallel(G1CollectedHeap::use_parallel_gc_threads()), _process_strings(process_strings), _strings_processed(0), _strings_removed(0), _process_symbols(process_symbols), _symbols_processed(0), _symbols_removed(0) { @@ -4807,10 +4796,10 @@ } ~G1StringSymbolTableUnlinkTask() { - guarantee(!_process_strings || !_do_in_parallel || StringTable::parallel_claimed_index() >= _initial_string_table_size, + guarantee(!_process_strings || StringTable::parallel_claimed_index() >= _initial_string_table_size, err_msg("claim value %d after unlink less than initial string table size %d", StringTable::parallel_claimed_index(), _initial_string_table_size)); - guarantee(!_process_symbols || !_do_in_parallel || SymbolTable::parallel_claimed_index() >= _initial_symbol_table_size, + guarantee(!_process_symbols || SymbolTable::parallel_claimed_index() >= _initial_symbol_table_size, err_msg("claim value %d after unlink less than initial symbol table size %d", SymbolTable::parallel_claimed_index(), _initial_symbol_table_size)); @@ -4824,28 +4813,19 @@ } void work(uint worker_id) { - if (_do_in_parallel) { - int strings_processed = 0; - int strings_removed = 0; - int symbols_processed = 0; - int symbols_removed = 0; - if (_process_strings) { - StringTable::possibly_parallel_unlink(_is_alive, &strings_processed, &strings_removed); - Atomic::add(strings_processed, &_strings_processed); - Atomic::add(strings_removed, &_strings_removed); - } - if (_process_symbols) { - SymbolTable::possibly_parallel_unlink(&symbols_processed, &symbols_removed); - Atomic::add(symbols_processed, &_symbols_processed); - Atomic::add(symbols_removed, &_symbols_removed); - } - } else { - if (_process_strings) { - StringTable::unlink(_is_alive, &_strings_processed, &_strings_removed); - } - if (_process_symbols) { - SymbolTable::unlink(&_symbols_processed, &_symbols_removed); - } + int strings_processed = 0; + int strings_removed = 0; + int symbols_processed = 0; + int symbols_removed = 0; + if (_process_strings) { + StringTable::possibly_parallel_unlink(_is_alive, &strings_processed, &strings_removed); + Atomic::add(strings_processed, &_strings_processed); + Atomic::add(strings_removed, &_strings_removed); + } + if (_process_symbols) { + SymbolTable::possibly_parallel_unlink(&symbols_processed, &symbols_removed); + Atomic::add(symbols_processed, &_symbols_processed); + Atomic::add(symbols_removed, &_symbols_removed); } } @@ -5013,6 +4993,10 @@ clean_nmethod(claimed_nmethods[i]); } } + + // The nmethod cleaning helps out and does the CodeCache part of MetadataOnStackMark. + // Need to retire the buffers now that this thread has stopped cleaning nmethods. + MetadataOnStackMark::retire_buffer_for_thread(Thread::current()); } void work_second_pass(uint worker_id) { @@ -5065,6 +5049,9 @@ // G1 specific cleanup work that has // been moved here to be done in parallel. ik->clean_dependent_nmethods(); + if (JvmtiExport::has_redefined_a_class()) { + InstanceKlass::purge_previous_versions(ik); + } } void work() { @@ -5099,8 +5086,18 @@ _klass_cleaning_task(is_alive) { } + void pre_work_verification() { + assert(!MetadataOnStackMark::has_buffer_for_thread(Thread::current()), "Should be empty"); + } + + void post_work_verification() { + assert(!MetadataOnStackMark::has_buffer_for_thread(Thread::current()), "Should be empty"); + } + // The parallel work done by all worker threads. void work(uint worker_id) { + pre_work_verification(); + // Do first pass of code cache cleaning. _code_cache_task.work_first_pass(worker_id); @@ -5119,6 +5116,8 @@ // Clean all klasses that were not unloaded. _klass_cleaning_task.work(); + + post_work_verification(); } }; @@ -5127,33 +5126,23 @@ bool process_strings, bool process_symbols, bool class_unloading_occurred) { - uint n_workers = (G1CollectedHeap::use_parallel_gc_threads() ? - workers()->active_workers() : 1); + uint n_workers = workers()->active_workers(); G1ParallelCleaningTask g1_unlink_task(is_alive, process_strings, process_symbols, n_workers, class_unloading_occurred); - if (G1CollectedHeap::use_parallel_gc_threads()) { - set_par_threads(n_workers); - workers()->run_task(&g1_unlink_task); - set_par_threads(0); - } else { - g1_unlink_task.work(0); - } + set_par_threads(n_workers); + workers()->run_task(&g1_unlink_task); + set_par_threads(0); } void G1CollectedHeap::unlink_string_and_symbol_table(BoolObjectClosure* is_alive, bool process_strings, bool process_symbols) { { - uint n_workers = (G1CollectedHeap::use_parallel_gc_threads() ? - _g1h->workers()->active_workers() : 1); + uint n_workers = _g1h->workers()->active_workers(); G1StringSymbolTableUnlinkTask g1_unlink_task(is_alive, process_strings, process_symbols); - if (G1CollectedHeap::use_parallel_gc_threads()) { - set_par_threads(n_workers); - workers()->run_task(&g1_unlink_task); - set_par_threads(0); - } else { - g1_unlink_task.work(0); - } + set_par_threads(n_workers); + workers()->run_task(&g1_unlink_task); + set_par_threads(0); } if (G1StringDedup::is_enabled()) { @@ -5171,11 +5160,7 @@ double start_time = os::elapsedTime(); RedirtyLoggedCardTableEntryClosure cl; - if (G1CollectedHeap::heap()->use_parallel_gc_threads()) { - _queue->par_apply_closure_to_all_completed_buffers(&cl); - } else { - _queue->apply_closure_to_all_completed_buffers(&cl); - } + _queue->par_apply_closure_to_all_completed_buffers(&cl); G1GCPhaseTimes* timer = G1CollectedHeap::heap()->g1_policy()->phase_times(); timer->record_redirty_logged_cards_time_ms(worker_id, (os::elapsedTime() - start_time) * 1000.0); @@ -5186,18 +5171,13 @@ void G1CollectedHeap::redirty_logged_cards() { double redirty_logged_cards_start = os::elapsedTime(); - uint n_workers = (G1CollectedHeap::use_parallel_gc_threads() ? - _g1h->workers()->active_workers() : 1); + uint n_workers = _g1h->workers()->active_workers(); G1RedirtyLoggedCardsTask redirty_task(&dirty_card_queue_set()); dirty_card_queue_set().reset_for_par_iteration(); - if (use_parallel_gc_threads()) { - set_par_threads(n_workers); - workers()->run_task(&redirty_task); - set_par_threads(0); - } else { - redirty_task.work(0); - } + set_par_threads(n_workers); + workers()->run_task(&redirty_task); + set_par_threads(0); DirtyCardQueueSet& dcq = JavaThread::dirty_card_queue_set(); dcq.merge_bufferlists(&dirty_card_queue_set()); @@ -5587,20 +5567,14 @@ // referents points to another object which is also referenced by an // object discovered by the STW ref processor. - assert(!G1CollectedHeap::use_parallel_gc_threads() || - no_of_gc_workers == workers()->active_workers(), - "Need to reset active GC workers"); + assert(no_of_gc_workers == workers()->active_workers(), "Need to reset active GC workers"); set_par_threads(no_of_gc_workers); G1ParPreserveCMReferentsTask keep_cm_referents(this, no_of_gc_workers, _task_queues); - if (G1CollectedHeap::use_parallel_gc_threads()) { - workers()->run_task(&keep_cm_referents); - } else { - keep_cm_referents.work(0); - } + workers()->run_task(&keep_cm_referents); set_par_threads(0); @@ -5727,21 +5701,15 @@ hot_card_cache->set_use_cache(false); uint n_workers; - if (G1CollectedHeap::use_parallel_gc_threads()) { - n_workers = - AdaptiveSizePolicy::calc_active_workers(workers()->total_workers(), - workers()->active_workers(), - Threads::number_of_non_daemon_threads()); - assert(UseDynamicNumberOfGCThreads || - n_workers == workers()->total_workers(), - "If not dynamic should be using all the workers"); - workers()->set_active_workers(n_workers); - set_par_threads(n_workers); - } else { - assert(n_par_threads() == 0, - "Should be the original non-parallel value"); - n_workers = 1; - } + n_workers = + AdaptiveSizePolicy::calc_active_workers(workers()->total_workers(), + workers()->active_workers(), + Threads::number_of_non_daemon_threads()); + assert(UseDynamicNumberOfGCThreads || + n_workers == workers()->total_workers(), + "If not dynamic should be using all the workers"); + workers()->set_active_workers(n_workers); + set_par_threads(n_workers); G1ParTask g1_par_task(this, _task_queues); @@ -5760,18 +5728,13 @@ ClassLoaderDataGraph::clear_claimed_marks(); } - if (G1CollectedHeap::use_parallel_gc_threads()) { - // The individual threads will set their evac-failure closures. - if (PrintTerminationStats) G1ParScanThreadState::print_termination_stats_hdr(); - // These tasks use ShareHeap::_process_strong_tasks - assert(UseDynamicNumberOfGCThreads || - workers()->active_workers() == workers()->total_workers(), - "If not dynamic should be using all the workers"); - workers()->run_task(&g1_par_task); - } else { - g1_par_task.set_for_termination(n_workers); - g1_par_task.work(0); - } + // The individual threads will set their evac-failure closures. + if (PrintTerminationStats) G1ParScanThreadState::print_termination_stats_hdr(); + // These tasks use ShareHeap::_process_strong_tasks + assert(UseDynamicNumberOfGCThreads || + workers()->active_workers() == workers()->total_workers(), + "If not dynamic should be using all the workers"); + workers()->run_task(&g1_par_task); end_par_time_sec = os::elapsedTime(); // Closing the inner scope will execute the destructor @@ -6077,22 +6040,9 @@ // Iterate over the dirty cards region list. G1ParCleanupCTTask cleanup_task(ct_bs, this); - if (G1CollectedHeap::use_parallel_gc_threads()) { - set_par_threads(); - workers()->run_task(&cleanup_task); - set_par_threads(0); - } else { - while (_dirty_cards_region_list) { - HeapRegion* r = _dirty_cards_region_list; - cleanup_task.clear_cards(r); - _dirty_cards_region_list = r->get_next_dirty_cards_region(); - if (_dirty_cards_region_list == r) { - // The last region. - _dirty_cards_region_list = NULL; - } - r->set_next_dirty_cards_region(NULL); - } - } + set_par_threads(); + workers()->run_task(&cleanup_task); + set_par_threads(0); #ifndef PRODUCT if (G1VerifyCTCleanup || VerifyAfterGC) { G1VerifyCardTableCleanup cleanup_verifier(this, ct_bs); @@ -6632,7 +6582,6 @@ void G1CollectedHeap::set_par_threads() { // Don't change the number of workers. Use the value previously set // in the workgroup. - assert(G1CollectedHeap::use_parallel_gc_threads(), "shouldn't be here otherwise"); uint n_workers = workers()->active_workers(); assert(UseDynamicNumberOfGCThreads || n_workers == workers()->total_workers(),
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -84,8 +84,7 @@ }; G1CollectorPolicy::G1CollectorPolicy() : - _parallel_gc_threads(G1CollectedHeap::use_parallel_gc_threads() - ? ParallelGCThreads : 1), + _parallel_gc_threads(ParallelGCThreads), _recent_gc_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)), _stop_world_start(0.0), @@ -1544,32 +1543,6 @@ } } -class KnownGarbageClosure: public HeapRegionClosure { - G1CollectedHeap* _g1h; - CollectionSetChooser* _hrSorted; - -public: - KnownGarbageClosure(CollectionSetChooser* hrSorted) : - _g1h(G1CollectedHeap::heap()), _hrSorted(hrSorted) { } - - bool doHeapRegion(HeapRegion* r) { - // We only include humongous regions in collection - // sets when concurrent mark shows that their contained object is - // unreachable. - - // Do we have any marking information for this region? - if (r->is_marked()) { - // We will skip any region that's currently used as an old GC - // alloc region (we should not consider those for collection - // before we fill them up). - if (_hrSorted->should_add(r) && !_g1h->is_old_gc_alloc_region(r)) { - _hrSorted->add_region(r); - } - } - return false; - } -}; - class ParKnownGarbageHRClosure: public HeapRegionClosure { G1CollectedHeap* _g1h; CSetChooserParUpdater _cset_updater; @@ -1617,34 +1590,29 @@ _collectionSetChooser->clear(); uint region_num = _g1->num_regions(); - if (G1CollectedHeap::use_parallel_gc_threads()) { - const uint OverpartitionFactor = 4; - uint WorkUnit; - // The use of MinChunkSize = 8 in the original code - // causes some assertion failures when the total number of - // region is less than 8. The code here tries to fix that. - // Should the original code also be fixed? - if (no_of_gc_threads > 0) { - const uint MinWorkUnit = MAX2(region_num / no_of_gc_threads, 1U); - WorkUnit = MAX2(region_num / (no_of_gc_threads * OverpartitionFactor), - MinWorkUnit); - } else { - assert(no_of_gc_threads > 0, - "The active gc workers should be greater than 0"); - // In a product build do something reasonable to avoid a crash. - const uint MinWorkUnit = MAX2(region_num / (uint) ParallelGCThreads, 1U); - WorkUnit = - MAX2(region_num / (uint) (ParallelGCThreads * OverpartitionFactor), - MinWorkUnit); - } - _collectionSetChooser->prepare_for_par_region_addition(_g1->num_regions(), - WorkUnit); - ParKnownGarbageTask parKnownGarbageTask(_collectionSetChooser, WorkUnit, (uint) no_of_gc_threads); - _g1->workers()->run_task(&parKnownGarbageTask); + const uint OverpartitionFactor = 4; + uint WorkUnit; + // The use of MinChunkSize = 8 in the original code + // causes some assertion failures when the total number of + // region is less than 8. The code here tries to fix that. + // Should the original code also be fixed? + if (no_of_gc_threads > 0) { + const uint MinWorkUnit = MAX2(region_num / no_of_gc_threads, 1U); + WorkUnit = MAX2(region_num / (no_of_gc_threads * OverpartitionFactor), + MinWorkUnit); } else { - KnownGarbageClosure knownGarbagecl(_collectionSetChooser); - _g1->heap_region_iterate(&knownGarbagecl); + assert(no_of_gc_threads > 0, + "The active gc workers should be greater than 0"); + // In a product build do something reasonable to avoid a crash. + const uint MinWorkUnit = MAX2(region_num / (uint) ParallelGCThreads, 1U); + WorkUnit = + MAX2(region_num / (uint) (ParallelGCThreads * OverpartitionFactor), + MinWorkUnit); } + _collectionSetChooser->prepare_for_par_region_addition(_g1->num_regions(), + WorkUnit); + ParKnownGarbageTask parKnownGarbageTask(_collectionSetChooser, WorkUnit, (uint) no_of_gc_threads); + _g1->workers()->run_task(&parKnownGarbageTask); _collectionSetChooser->sort_regions();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -292,36 +292,25 @@ if (_root_region_scan_wait_time_ms > 0.0) { print_stats(1, "Root Region Scan Waiting", _root_region_scan_wait_time_ms); } - if (G1CollectedHeap::use_parallel_gc_threads()) { - print_stats(1, "Parallel Time", _cur_collection_par_time_ms, _active_gc_threads); - _last_gc_worker_start_times_ms.print(2, "GC Worker Start (ms)"); - _last_ext_root_scan_times_ms.print(2, "Ext Root Scanning (ms)"); - if (_last_satb_filtering_times_ms.sum() > 0.0) { - _last_satb_filtering_times_ms.print(2, "SATB Filtering (ms)"); - } - _last_update_rs_times_ms.print(2, "Update RS (ms)"); - _last_update_rs_processed_buffers.print(3, "Processed Buffers"); - _last_scan_rs_times_ms.print(2, "Scan RS (ms)"); - _last_strong_code_root_scan_times_ms.print(2, "Code Root Scanning (ms)"); - _last_obj_copy_times_ms.print(2, "Object Copy (ms)"); - _last_termination_times_ms.print(2, "Termination (ms)"); - if (G1Log::finest()) { - _last_termination_attempts.print(3, "Termination Attempts"); - } - _last_gc_worker_other_times_ms.print(2, "GC Worker Other (ms)"); - _last_gc_worker_times_ms.print(2, "GC Worker Total (ms)"); - _last_gc_worker_end_times_ms.print(2, "GC Worker End (ms)"); - } else { - _last_ext_root_scan_times_ms.print(1, "Ext Root Scanning (ms)"); - if (_last_satb_filtering_times_ms.sum() > 0.0) { - _last_satb_filtering_times_ms.print(1, "SATB Filtering (ms)"); - } - _last_update_rs_times_ms.print(1, "Update RS (ms)"); - _last_update_rs_processed_buffers.print(2, "Processed Buffers"); - _last_scan_rs_times_ms.print(1, "Scan RS (ms)"); - _last_strong_code_root_scan_times_ms.print(1, "Code Root Scanning (ms)"); - _last_obj_copy_times_ms.print(1, "Object Copy (ms)"); + print_stats(1, "Parallel Time", _cur_collection_par_time_ms, _active_gc_threads); + _last_gc_worker_start_times_ms.print(2, "GC Worker Start (ms)"); + _last_ext_root_scan_times_ms.print(2, "Ext Root Scanning (ms)"); + if (_last_satb_filtering_times_ms.sum() > 0.0) { + _last_satb_filtering_times_ms.print(2, "SATB Filtering (ms)"); } + _last_update_rs_times_ms.print(2, "Update RS (ms)"); + _last_update_rs_processed_buffers.print(3, "Processed Buffers"); + _last_scan_rs_times_ms.print(2, "Scan RS (ms)"); + _last_strong_code_root_scan_times_ms.print(2, "Code Root Scanning (ms)"); + _last_obj_copy_times_ms.print(2, "Object Copy (ms)"); + _last_termination_times_ms.print(2, "Termination (ms)"); + if (G1Log::finest()) { + _last_termination_attempts.print(3, "Termination Attempts"); + } + _last_gc_worker_other_times_ms.print(2, "GC Worker Other (ms)"); + _last_gc_worker_times_ms.print(2, "GC Worker Total (ms)"); + _last_gc_worker_end_times_ms.print(2, "GC Worker End (ms)"); + print_stats(1, "Code Root Fixup", _cur_collection_code_root_fixup_time_ms); print_stats(1, "Code Root Purge", _cur_strong_code_root_purge_time_ms); if (G1StringDedup::is_enabled()) {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -43,7 +43,7 @@ _hot_cache_idx = 0; // For refining the cards in the hot cache in parallel - _hot_cache_par_chunk_size = (ParallelGCThreads > 0 ? ClaimChunkSize : _hot_cache_size); + _hot_cache_par_chunk_size = ClaimChunkSize; _hot_cache_par_claimed_idx = 0; _card_counts.initialize(card_counts_storage); @@ -119,7 +119,7 @@ // RSet updating while within an evacuation pause. // In this case worker_i should be the id of a GC worker thread assert(SafepointSynchronize::is_at_safepoint(), "Should be at a safepoint"); - assert(worker_i < (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), + assert(worker_i < ParallelGCThreads, err_msg("incorrect worker id: %u", worker_i)); into_cset_dcq->enqueue(card_ptr);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -80,7 +80,6 @@ _prev_period_summary() { _seq_task = new SubTasksDone(NumSeqTasks); - guarantee(n_workers() > 0, "There should be some workers"); _cset_rs_update_cl = NEW_C_HEAP_ARRAY(OopsInHeapRegionClosure*, n_workers(), mtGC); for (uint i = 0; i < n_workers(); i++) { _cset_rs_update_cl[i] = NULL; @@ -282,7 +281,7 @@ // is during RSet updating within an evacuation pause. // In this case worker_i should be the id of a GC worker thread. assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause"); - assert(worker_i < (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), "should be a GC worker"); + assert(worker_i < ParallelGCThreads, "should be a GC worker"); if (_g1rs->refine_card(card_ptr, worker_i, true)) { // 'card_ptr' contains references that point into the collection @@ -343,8 +342,6 @@ // DirtyCardQueueSet that is used to manage RSet updates DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set()); - assert((ParallelGCThreads > 0) || worker_i == 0, "invariant"); - updateRS(&into_cset_dcq, worker_i); scanRS(oc, code_root_cl, worker_i); @@ -420,12 +417,7 @@ } }; -void G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm) { - ScrubRSClosure scrub_cl(region_bm, card_bm); - _g1->heap_region_iterate(&scrub_cl); -} - -void G1RemSet::scrub_par(BitMap* region_bm, BitMap* card_bm, uint worker_num, HeapRegionClaimer *hrclaimer) { +void G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm, uint worker_num, HeapRegionClaimer *hrclaimer) { ScrubRSClosure scrub_cl(region_bm, card_bm); _g1->heap_region_par_iterate(&scrub_cl, worker_num, hrclaimer); }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp Wed Jul 05 20:05:54 2017 +0200 @@ -124,14 +124,10 @@ // Requires "region_bm" and "card_bm" to be bitmaps with 1 bit per region // or card, respectively, such that a region or card with a corresponding // 0 bit contains no part of any live object. Eliminates any remembered - // set entries that correspond to dead heap ranges. - void scrub(BitMap* region_bm, BitMap* card_bm); - - // Like the above, but assumes is called in parallel: "worker_num" is the - // parallel thread id of the current thread, and "hrclaimer" is the shared - // HeapRegionClaimer that should be used to claim heap regions. - void scrub_par(BitMap* region_bm, BitMap* card_bm, - uint worker_num, HeapRegionClaimer* hrclaimer); + // set entries that correspond to dead heap ranges. "worker_num" is the + // parallel thread id of the current thread, and "hrclaimer" is the + // HeapRegionClaimer that should be used. + void scrub(BitMap* region_bm, BitMap* card_bm, uint worker_num, HeapRegionClaimer* hrclaimer); // Refine the card corresponding to "card_ptr". // If check_for_refs_into_cset is true, a true result is returned
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp Wed Jul 05 20:05:54 2017 +0200 @@ -31,11 +31,7 @@ #include "oops/oop.inline.hpp" inline uint G1RemSet::n_workers() { - if (_g1->workers() != NULL) { - return _g1->workers()->total_workers(); - } else { - return 1; - } + return _g1->workers()->total_workers(); } template <class T>
--- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -154,14 +154,10 @@ double fixup_start = os::elapsedTime(); G1StringDedupUnlinkOrOopsDoTask task(is_alive, keep_alive, allow_resize_and_rehash); - if (G1CollectedHeap::use_parallel_gc_threads()) { - G1CollectedHeap* g1h = G1CollectedHeap::heap(); - g1h->set_par_threads(); - g1h->workers()->run_task(&task); - g1h->set_par_threads(0); - } else { - task.work(0); - } + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + g1h->set_par_threads(); + g1h->workers()->run_task(&task); + g1h->set_par_threads(0); double fixup_time_ms = (os::elapsedTime() - fixup_start) * 1000.0; g1p->phase_times()->record_string_dedup_fixup_time(fixup_time_ms);
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -202,7 +202,7 @@ #endif // _MSC_VER SATBMarkQueueSet::SATBMarkQueueSet() : - PtrQueueSet(), _closure(NULL), _par_closures(NULL), + PtrQueueSet(), _closures(NULL), _shared_satb_queue(this, true /*perm*/) { } void SATBMarkQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock, @@ -210,9 +210,7 @@ Mutex* lock) { PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold, -1); _shared_satb_queue.set_lock(lock); - if (ParallelGCThreads > 0) { - _par_closures = NEW_C_HEAP_ARRAY(ObjectClosure*, ParallelGCThreads, mtGC); - } + _closures = NEW_C_HEAP_ARRAY(ObjectClosure*, ParallelGCThreads, mtGC); } void SATBMarkQueueSet::handle_zero_index_for_thread(JavaThread* t) { @@ -276,17 +274,13 @@ shared_satb_queue()->filter(); } -void SATBMarkQueueSet::set_closure(ObjectClosure* closure) { - _closure = closure; +void SATBMarkQueueSet::set_closure(uint worker, ObjectClosure* closure) { + assert(_closures != NULL, "Precondition"); + assert(worker < ParallelGCThreads, "Worker index must be in range [0...ParallelGCThreads)"); + _closures[worker] = closure; } -void SATBMarkQueueSet::set_par_closure(int i, ObjectClosure* par_closure) { - assert(ParallelGCThreads > 0 && _par_closures != NULL, "Precondition"); - _par_closures[i] = par_closure; -} - -bool SATBMarkQueueSet::apply_closure_to_completed_buffer_work(bool par, - uint worker) { +bool SATBMarkQueueSet::apply_closure_to_completed_buffer(uint worker) { BufferNode* nd = NULL; { MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); @@ -298,7 +292,7 @@ if (_n_completed_buffers == 0) _process_completed = false; } } - ObjectClosure* cl = (par ? _par_closures[worker] : _closure); + ObjectClosure* cl = _closures[worker]; if (nd != NULL) { void **buf = BufferNode::make_buffer_from_node(nd); ObjPtrQueue::apply_closure_to_buffer(cl, buf, 0, _sz);
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp Wed Jul 05 20:05:54 2017 +0200 @@ -78,16 +78,10 @@ }; class SATBMarkQueueSet: public PtrQueueSet { - ObjectClosure* _closure; - ObjectClosure** _par_closures; // One per ParGCThread. + ObjectClosure** _closures; // One per ParGCThread. ObjPtrQueue _shared_satb_queue; - // Utility function to support sequential and parallel versions. If - // "par" is true, then "worker" is the par thread id; if "false", worker - // is ignored. - bool apply_closure_to_completed_buffer_work(bool par, uint worker); - #ifdef ASSERT void dump_active_states(bool expected_active); void verify_active_states(bool expected_active); @@ -111,26 +105,16 @@ // Filter all the currently-active SATB buffers. void filter_thread_buffers(); - // Register "blk" as "the closure" for all queues. Only one such closure - // is allowed. The "apply_closure_to_completed_buffer" method will apply - // this closure to a completed buffer, and "iterate_closure_all_threads" + // Register closure for the given worker thread. The "apply_closure_to_completed_buffer" + // method will apply this closure to a completed buffer, and "iterate_closure_all_threads" // applies it to partially-filled buffers (the latter should only be done // with the world stopped). - void set_closure(ObjectClosure* closure); - // Set the parallel closures: pointer is an array of pointers to - // closures, one for each parallel GC thread. - void set_par_closure(int i, ObjectClosure* closure); + void set_closure(uint worker, ObjectClosure* closure); // If there exists some completed buffer, pop it, then apply the // registered closure to all its elements, and return true. If no // completed buffers exist, return false. - bool apply_closure_to_completed_buffer() { - return apply_closure_to_completed_buffer_work(false, 0); - } - // Parallel version of the above. - bool par_apply_closure_to_completed_buffer(uint worker) { - return apply_closure_to_completed_buffer_work(true, worker); - } + bool apply_closure_to_completed_buffer(uint worker); // Apply the given closure on enqueued and currently-active buffers // respectively. Both methods are read-only, i.e., they do not
--- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp Wed Jul 05 20:05:54 2017 +0200 @@ -60,7 +60,7 @@ VM_G1CollectFull(unsigned int gc_count_before, unsigned int full_gc_count_before, GCCause::Cause cause) - : VM_GC_Operation(gc_count_before, cause, full_gc_count_before) { } + : VM_GC_Operation(gc_count_before, cause, full_gc_count_before, true) { } virtual VMOp_Type type() const { return VMOp_G1CollectFull; } virtual void doit(); virtual const char* name() const {
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -479,7 +479,7 @@ _next_gen.par_oop_since_save_marks_iterate_done(i); } - if (UseConcMarkSweepGC && ParallelGCThreads > 0) { + if (UseConcMarkSweepGC) { // We need to call this even when ResizeOldPLAB is disabled // so as to avoid breaking some asserts. While we may be able // to avoid this by reorganizing the code a bit, I am loathe
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -47,11 +47,6 @@ // Do basic sizing work GenCollectorPolicy::initialize_flags(); - assert(UseSerialGC || - !FLAG_IS_DEFAULT(ParallelGCThreads) || - (ParallelGCThreads > 0), - "ParallelGCThreads should be set before flag initialization"); - // The survivor ratio's are calculated "raw", unlike the // default gc, which adds 2 to the ratio value. We need to // make sure the values are valid before using them.
--- a/hotspot/src/share/vm/memory/freeBlockDictionary.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/memory/freeBlockDictionary.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -43,12 +43,10 @@ template <class Chunk> void FreeBlockDictionary<Chunk>::verify_par_locked() const { #ifdef ASSERT - if (ParallelGCThreads > 0) { - Thread* my_thread = Thread::current(); - if (my_thread->is_GC_task_thread()) { - assert(par_lock() != NULL, "Should be using locking?"); - assert_lock_strong(par_lock()); - } + Thread* my_thread = Thread::current(); + if (my_thread->is_GC_task_thread()) { + assert(par_lock() != NULL, "Should be using locking?"); + assert_lock_strong(par_lock()); } #endif // ASSERT }
--- a/hotspot/src/share/vm/memory/freeList.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/memory/freeList.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -287,11 +287,14 @@ return false; } -#ifndef PRODUCT +#ifdef ASSERT template <class Chunk> void FreeList<Chunk>::assert_proper_lock_protection_work() const { - assert(protecting_lock() != NULL, "Don't call this directly"); - assert(ParallelGCThreads > 0, "Don't call this directly"); + // Nothing to do if the list has no assigned protecting lock + if (protecting_lock() == NULL) { + return; + } + Thread* thr = Thread::current(); if (thr->is_VM_thread() || thr->is_ConcurrentGC_thread()) { // assert that we are holding the freelist lock
--- a/hotspot/src/share/vm/memory/freeList.hpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/memory/freeList.hpp Wed Jul 05 20:05:54 2017 +0200 @@ -56,15 +56,12 @@ #ifdef ASSERT Mutex* _protecting_lock; + void assert_proper_lock_protection_work() const; #endif // Asserts false if the protecting lock (if any) is not held. - void assert_proper_lock_protection_work() const PRODUCT_RETURN; void assert_proper_lock_protection() const { -#ifdef ASSERT - if (_protecting_lock != NULL) - assert_proper_lock_protection_work(); -#endif + DEBUG_ONLY(assert_proper_lock_protection_work()); } void increment_count() {
--- a/hotspot/src/share/vm/memory/sharedHeap.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/memory/sharedHeap.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -68,11 +68,9 @@ vm_exit_during_initialization("Failed necessary allocation."); } _sh = this; // ch is static, should be set only once. - if ((UseParNewGC || - (UseConcMarkSweepGC && (CMSParallelInitialMarkEnabled || - CMSParallelRemarkEnabled)) || - UseG1GC) && - ParallelGCThreads > 0) { + if (UseParNewGC || + UseG1GC || + (UseConcMarkSweepGC && (CMSParallelInitialMarkEnabled || CMSParallelRemarkEnabled) && use_parallel_gc_threads())) { _workers = new FlexibleWorkGang("Parallel GC Threads", ParallelGCThreads, /* are_GC_task_threads */true, /* are_ConcurrentGC_threads */false);
--- a/hotspot/src/share/vm/oops/constantPool.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/oops/constantPool.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -1779,11 +1779,22 @@ void ConstantPool::set_on_stack(const bool value) { if (value) { - _flags |= _on_stack; + int old_flags = *const_cast<volatile int *>(&_flags); + while ((old_flags & _on_stack) == 0) { + int new_flags = old_flags | _on_stack; + int result = Atomic::cmpxchg(new_flags, &_flags, old_flags); + + if (result == old_flags) { + // Succeeded. + MetadataOnStackMark::record(this, Thread::current()); + return; + } + old_flags = result; + } } else { + // Clearing is done single-threadedly. _flags &= ~_on_stack; } - if (value) MetadataOnStackMark::record(this); } // JSR 292 support for patching constant pool oops after the class is linked and
--- a/hotspot/src/share/vm/oops/method.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/oops/method.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -1862,9 +1862,12 @@ void Method::set_on_stack(const bool value) { // Set both the method itself and its constant pool. The constant pool // on stack means some method referring to it is also on the stack. - _access_flags.set_on_stack(value); constants()->set_on_stack(value); - if (value) MetadataOnStackMark::record(this); + + bool succeeded = _access_flags.set_on_stack(value); + if (value && succeeded) { + MetadataOnStackMark::record(this, Thread::current()); + } } // Called when the class loader is unloaded to make all methods weak.
--- a/hotspot/src/share/vm/prims/jni.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/prims/jni.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -3861,6 +3861,7 @@ void TestBitMap_test(); void TestAsUtf8(); void Test_linked_list(); +void TestChunkedList_test(); #if INCLUDE_ALL_GCS void TestOldFreeSpaceCalculation_test(); void TestG1BiasedArray_test(); @@ -3894,6 +3895,7 @@ run_unit_test(TestAsUtf8()); run_unit_test(ObjectMonitor::sanity_checks()); run_unit_test(Test_linked_list()); + run_unit_test(TestChunkedList_test()); #if INCLUDE_VM_STRUCTS run_unit_test(VMStructs::test()); #endif
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -3782,27 +3782,33 @@ bool settings_file_specified = false; bool needs_hotspotrc_warning = false; - ArgumentsExt::process_options(args); - const char* flags_file; int index; for (index = 0; index < args->nOptions; index++) { const JavaVMOption *option = args->options + index; + if (ArgumentsExt::process_options(option)) { + continue; + } if (match_option(option, "-XX:Flags=", &tail)) { flags_file = tail; settings_file_specified = true; + continue; } if (match_option(option, "-XX:+PrintVMOptions", &tail)) { PrintVMOptions = true; + continue; } if (match_option(option, "-XX:-PrintVMOptions", &tail)) { PrintVMOptions = false; + continue; } if (match_option(option, "-XX:+IgnoreUnrecognizedVMOptions", &tail)) { IgnoreUnrecognizedVMOptions = true; + continue; } if (match_option(option, "-XX:-IgnoreUnrecognizedVMOptions", &tail)) { IgnoreUnrecognizedVMOptions = false; + continue; } if (match_option(option, "-XX:+PrintFlagsInitial", &tail)) { CommandLineFlags::printFlags(tty, false); @@ -3824,6 +3830,7 @@ } else { vm_exit_during_initialization("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]", NULL); } + continue; } #endif
--- a/hotspot/src/share/vm/runtime/arguments_ext.hpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/runtime/arguments_ext.hpp Wed Jul 05 20:05:54 2017 +0200 @@ -34,7 +34,10 @@ static inline bool check_gc_consistency_user(); static inline bool check_gc_consistency_ergo(); static inline bool check_vm_args_consistency(); - static void process_options(const JavaVMInitArgs* args) {} + // The argument processing extension. Returns true if there is + // no additional parsing needed in Arguments::parse() for the option. + // Otherwise returns false. + static inline bool process_options(const JavaVMOption *option) { return false; } }; void ArgumentsExt::select_gc_ergonomically() {
--- a/hotspot/src/share/vm/runtime/thread.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/runtime/thread.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -201,6 +201,8 @@ // This initial value ==> never claimed. _oops_do_parity = 0; + _metadata_on_stack_buffer = NULL; + // the handle mark links itself to last_handle_mark new HandleMark(this);
--- a/hotspot/src/share/vm/runtime/thread.hpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/runtime/thread.hpp Wed Jul 05 20:05:54 2017 +0200 @@ -42,11 +42,10 @@ #include "runtime/threadLocalStorage.hpp" #include "runtime/thread_ext.hpp" #include "runtime/unhandledOops.hpp" -#include "utilities/macros.hpp" - #include "trace/traceBackend.hpp" #include "trace/traceMacros.hpp" #include "utilities/exceptions.hpp" +#include "utilities/macros.hpp" #include "utilities/top.hpp" #if INCLUDE_ALL_GCS #include "gc_implementation/g1/dirtyCardQueue.hpp" @@ -83,6 +82,10 @@ class ThreadClosure; class IdealGraphPrinter; +class Metadata; +template <class T, MEMFLAGS F> class ChunkedList; +typedef ChunkedList<Metadata*, mtInternal> MetadataOnStackBuffer; + DEBUG_ONLY(class ResourceMark;) class WorkerThread; @@ -255,6 +258,9 @@ jlong _allocated_bytes; // Cumulative number of bytes allocated on // the Java heap + // Thread-local buffer used by MetadataOnStackMark. + MetadataOnStackBuffer* _metadata_on_stack_buffer; + TRACE_DATA _trace_data; // Thread-local data for tracing ThreadExt _ext; @@ -490,7 +496,10 @@ // creation fails due to lack of memory, too many threads etc. bool set_as_starting_thread(); - protected: + void set_metadata_on_stack_buffer(MetadataOnStackBuffer* buffer) { _metadata_on_stack_buffer = buffer; } + MetadataOnStackBuffer* metadata_on_stack_buffer() const { return _metadata_on_stack_buffer; } + +protected: // OS data associated with the thread OSThread* _osthread; // Platform-specific thread information
--- a/hotspot/src/share/vm/utilities/accessFlags.cpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/utilities/accessFlags.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -47,6 +47,21 @@ } while(f != old_flags); } +// Returns true iff this thread succeeded setting the bit. +bool AccessFlags::atomic_set_one_bit(jint bit) { + // Atomically update the flags with the bit given + jint old_flags, new_flags, f; + bool is_setting_bit = false; + do { + old_flags = _flags; + new_flags = old_flags | bit; + is_setting_bit = old_flags != new_flags; + f = Atomic::cmpxchg(new_flags, &_flags, old_flags); + } while(f != old_flags); + + return is_setting_bit; +} + #if !defined(PRODUCT) || INCLUDE_JVMTI void AccessFlags::print_on(outputStream* st) const {
--- a/hotspot/src/share/vm/utilities/accessFlags.hpp Thu Oct 30 08:34:51 2014 -0700 +++ b/hotspot/src/share/vm/utilities/accessFlags.hpp Wed Jul 05 20:05:54 2017 +0200 @@ -172,6 +172,7 @@ // Atomic update of flags void atomic_set_bits(jint bits); + bool atomic_set_one_bit(jint bit); void atomic_clear_bits(jint bits); private: @@ -233,12 +234,13 @@ atomic_set_bits(JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE); } - void set_on_stack(const bool value) + bool set_on_stack(const bool value) { if (value) { - atomic_set_bits(JVM_ACC_ON_STACK); + return atomic_set_one_bit(JVM_ACC_ON_STACK); } else { atomic_clear_bits(JVM_ACC_ON_STACK); + return true; // Ignored } } // Conversion
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/utilities/chunkedList.cpp Wed Jul 05 20:05:54 2017 +0200 @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2014, 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. + * + */ + +#include "precompiled.hpp" +#include "utilities/chunkedList.hpp" +#include "utilities/debug.hpp" + +/////////////// Unit tests /////////////// + +#ifndef PRODUCT + +template <typename T> +class TestChunkedList { + typedef ChunkedList<T, mtOther> ChunkedListT; + + public: + static void testEmpty() { + ChunkedListT buffer; + assert(buffer.size() == 0, "assert"); + } + + static void testFull() { + ChunkedListT buffer; + for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) { + buffer.push((T)i); + } + assert(buffer.size() == ChunkedListT::BufferSize, "assert"); + assert(buffer.is_full(), "assert"); + } + + static void testSize() { + ChunkedListT buffer; + for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) { + assert(buffer.size() == i, "assert"); + buffer.push((T)i); + assert(buffer.size() == i + 1, "assert"); + } + } + + static void testClear() { + ChunkedListT buffer; + + buffer.clear(); + assert(buffer.size() == 0, "assert"); + + for (uintptr_t i = 0; i < ChunkedListT::BufferSize / 2; i++) { + buffer.push((T)i); + } + buffer.clear(); + assert(buffer.size() == 0, "assert"); + + for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) { + buffer.push((T)i); + } + buffer.clear(); + assert(buffer.size() == 0, "assert"); + } + + static void testAt() { + ChunkedListT buffer; + + for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) { + buffer.push((T)i); + assert(buffer.at(i) == (T)i, "assert"); + } + + for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) { + assert(buffer.at(i) == (T)i, "assert"); + } + } + + static void test() { + testEmpty(); + testFull(); + testSize(); + testClear(); + testAt(); + } +}; + +class Metadata; + +void TestChunkedList_test() { + TestChunkedList<Metadata*>::test(); + TestChunkedList<size_t>::test(); +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/utilities/chunkedList.hpp Wed Jul 05 20:05:54 2017 +0200 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2014, 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. + * + */ + +#ifndef SHARE_VM_UTILITIES_CHUNKED_LIST_HPP +#define SHARE_VM_UTILITIES_CHUNKED_LIST_HPP + +#include "memory/allocation.hpp" +#include "utilities/debug.hpp" + +template <class T, MEMFLAGS F> class ChunkedList : public CHeapObj<F> { + template <class U> friend class TestChunkedList; + + static const size_t BufferSize = 64; + + T _values[BufferSize]; + T* _top; + + ChunkedList<T, F>* _next_used; + ChunkedList<T, F>* _next_free; + + T const * end() const { + return &_values[BufferSize]; + } + + public: + ChunkedList<T, F>() : _top(_values), _next_used(NULL), _next_free(NULL) {} + + bool is_full() const { + return _top == end(); + } + + void clear() { + _top = _values; + // Don't clear the next pointers since that would interfere + // with other threads trying to iterate through the lists. + } + + void push(T m) { + assert(!is_full(), "Buffer is full"); + *_top = m; + _top++; + } + + void set_next_used(ChunkedList<T, F>* buffer) { _next_used = buffer; } + void set_next_free(ChunkedList<T, F>* buffer) { _next_free = buffer; } + + ChunkedList<T, F>* next_used() const { return _next_used; } + ChunkedList<T, F>* next_free() const { return _next_free; } + + size_t size() const { + return pointer_delta(_top, _values, sizeof(T)); + } + + T at(size_t i) { + assert(i < size(), err_msg("IOOBE i: " SIZE_FORMAT " size(): " SIZE_FORMAT, i, size())); + return _values[i]; + } +}; + +#endif // SHARE_VM_UTILITIES_CHUNKED_LIST_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/CommandLine/TestVMOptions.java Wed Jul 05 20:05:54 2017 +0200 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014, 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 8060256 + * @summary Test various command line options + * @library /testlibrary + * @run main TestVMOptions + */ + +import com.oracle.java.testlibrary.*; +import java.io.File; + +public class TestVMOptions { + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:bogus", + "-XX:+IgnoreUnrecognizedVMOptions", + "-XX:+PrintFlagsInitial"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("bool PrintGCDetails"); + + pb = ProcessTools.createJavaProcessBuilder( + "-XX:-PrintVMOptions", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("java version"); + + File dir = new File(System.getProperty("test.src", ".")); + File file = new File(dir, "flagfile.txt"); + String s = file.getAbsolutePath(); + pb = ProcessTools.createJavaProcessBuilder("-XX:Flags="+s); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("VM option '-IgnoreUnrecognizedVMOptions'"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/CommandLine/flagfile.txt Wed Jul 05 20:05:54 2017 +0200 @@ -0,0 +1,1 @@ ++PrintVMOptions -IgnoreUnrecognizedVMOptions
--- a/jdk/.hgtags Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/.hgtags Wed Jul 05 20:05:54 2017 +0200 @@ -279,3 +279,4 @@ 21568031434d7a9dbb0cc6516cc3183d349c2253 jdk9-b34 e549291a0227031310fa91c574891f892d27f959 jdk9-b35 cdcf2e599e42935c2d1d19a24bb19e808aeb43b5 jdk9-b36 +27c3345d6dce39a22c262f30bb1f0e0b00c3709e jdk9-b37
--- a/jdk/make/copy/Copy-java.base.gmk Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/make/copy/Copy-java.base.gmk Wed Jul 05 20:05:54 2017 +0200 @@ -48,22 +48,6 @@ ################################################################################ -CALENDARS_SRC := $(JDK_TOPDIR)/src/java.base/share/conf - -$(LIB_DST_DIR)/calendars.properties: $(CALENDARS_SRC)/calendars.properties - $(call install-file) - -BASE_CONF_FILES += $(LIB_DST_DIR)/calendars.properties - -$(LIB_DST_DIR)/hijrah-config-umalqura.properties: $(CALENDARS_SRC)/hijrah-config-umalqura.properties - $(MKDIR) -p $(@D) - $(RM) $@ - $(CP) $< $@ - -BASE_CONF_FILES += $(LIB_DST_DIR)/hijrah-config-umalqura.properties - -################################################################################ - ifneq ($(findstring $(OPENJDK_TARGET_OS), windows aix),) TZMAPPINGS_SRC := $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/conf
--- a/jdk/make/copy/Copy-java.desktop.gmk Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/make/copy/Copy-java.desktop.gmk Wed Jul 05 20:05:54 2017 +0200 @@ -67,8 +67,11 @@ FREETYPE_TARGET_LIB := $(JDK_OUTPUTDIR)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/$(call SHARED_LIBRARY,freetype).6 endif + # We can't use $(install-file) in this rule because it preserves symbolic links and + # libfreetype.so is usually a symbolic link to something like libfreetype.so.6 on Unix. $(FREETYPE_TARGET_LIB): $(FREETYPE_BUNDLE_LIB_PATH)/$(call SHARED_LIBRARY,freetype) - $(install-file) + $(MKDIR) -p $(@D) + $(CP) $< $@ ifeq ($(OPENJDK_BUILD_OS), windows) $(CHMOD) +rx $@ endif
--- a/jdk/make/data/tzdata/VERSION Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/make/data/tzdata/VERSION Wed Jul 05 20:05:54 2017 +0200 @@ -21,4 +21,4 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -tzdata2014g +tzdata2014i
--- a/jdk/make/data/tzdata/africa Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/make/data/tzdata/africa Wed Jul 05 20:05:54 2017 +0200 @@ -133,23 +133,13 @@ # See Africa/Lagos. # Botswana -# From Paul Eggert (2013-02-21): -# Milne says they were regulated by the Cape Town Signal in 1899; -# assume they switched to 2:00 when Cape Town did. -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Gaborone 1:43:40 - LMT 1885 - 1:30 - SAST 1903 Mar - 2:00 - CAT 1943 Sep 19 2:00 - 2:00 1:00 CAST 1944 Mar 19 2:00 - 2:00 - CAT +# See Africa/Maputo. # Burkina Faso # See Africa/Abidjan. # Burundi -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Bujumbura 1:57:28 - LMT 1890 - 2:00 - CAT +# See Africa/Maputo. # Cameroon # See Africa/Lagos. @@ -184,10 +174,7 @@ 3:00 - EAT # Democratic Republic of the Congo -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Lubumbashi 1:49:52 - LMT 1897 Nov 9 - 2:00 - CAT -# The above is for the eastern part; see Africa/Lagos for the western part. +# See Africa/Lagos for the western part and Africa/Maputo for the eastern. # Republic of the Congo # See Africa/Lagos. @@ -339,7 +326,7 @@ # Egypt is to change back to Daylight system on May 15 # http://english.ahram.org.eg/NewsContent/1/64/100735/Egypt/Politics-/Egypts-government-to-reapply-daylight-saving-time-.aspx -# From Gunther Vermier (2015-05-13): +# From Gunther Vermier (2014-05-13): # our Egypt office confirms that the change will be at 15 May "midnight" (24:00) # From Imed Chihi (2014-06-04): @@ -489,11 +476,7 @@ 3:00 - EAT # Lesotho -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Maseru 1:50:00 - LMT 1903 Mar - 2:00 - SAST 1943 Sep 19 2:00 - 2:00 1:00 SAST 1944 Mar 19 2:00 - 2:00 - SAST +# See Africa/Johannesburg. # Liberia # From Paul Eggert (2006-03-22): @@ -575,9 +558,7 @@ 3:00 - EAT # Malawi -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Blantyre 2:20:00 - LMT 1903 Mar - 2:00 - CAT +# See Africa/Maputo. # Mali # Mauritania @@ -987,6 +968,13 @@ # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Maputo 2:10:20 - LMT 1903 Mar 2:00 - CAT +Link Africa/Maputo Africa/Blantyre # Malawi +Link Africa/Maputo Africa/Bujumbura # Burundi +Link Africa/Maputo Africa/Gaborone # Botswana +Link Africa/Maputo Africa/Harare # Zimbabwe +Link Africa/Maputo Africa/Kigali # Rwanda +Link Africa/Maputo Africa/Lubumbashi # E Dem. Rep. of Congo +Link Africa/Maputo Africa/Lusaka # Zambia # Namibia # The 1994-04-03 transition is from Shanks & Pottenger. @@ -1054,9 +1042,7 @@ # Tromelin - inhabited until at least 1958 # Rwanda -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Kigali 2:00:16 - LMT 1935 Jun - 2:00 - CAT +# See Africa/Maputo. # St Helena # See Africa/Abidjan. @@ -1100,6 +1086,9 @@ Zone Africa/Johannesburg 1:52:00 - LMT 1892 Feb 8 1:30 - SAST 1903 Mar 2:00 SA SAST +Link Africa/Johannesburg Africa/Maseru # Lesotho +Link Africa/Johannesburg Africa/Mbabane # Swaziland +# # Marion and Prince Edward Is # scientific station since 1947 # no information @@ -1127,9 +1116,7 @@ Link Africa/Khartoum Africa/Juba # Swaziland -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Mbabane 2:04:24 - LMT 1903 Mar - 2:00 - SAST +# See Africa/Johannesburg. # Tanzania # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -1250,11 +1237,5 @@ 3:00 - EAT # Zambia -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Lusaka 1:53:08 - LMT 1903 Mar - 2:00 - CAT - # Zimbabwe -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Africa/Harare 2:04:12 - LMT 1903 Mar - 2:00 - CAT +# See Africa/Maputo.
--- a/jdk/make/data/tzdata/asia Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/make/data/tzdata/asia Wed Jul 05 20:05:54 2017 +0200 @@ -70,10 +70,11 @@ # 3:30 IRST IRDT Iran # 4:00 GST Gulf* # 5:30 IST India -# 7:00 ICT Indochina* +# 7:00 ICT Indochina, most times and locations* # 7:00 WIB west Indonesia (Waktu Indonesia Barat) # 8:00 WITA central Indonesia (Waktu Indonesia Tengah) # 8:00 CST China +# 8:00 IDT Indochina, 1943-45, 1947-55, 1960-75 (some locations)* # 8:00 JWST Western Standard Time (Japan, 1896/1937)* # 9:00 JCST Central Standard Time (Japan, 1896/1937) # 9:00 WIT east Indonesia (Waktu Indonesia Timur) @@ -294,12 +295,8 @@ 6:30 - MMT # Myanmar Time # Cambodia -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Asia/Phnom_Penh 6:59:40 - LMT 1906 Jun 9 - 7:06:20 - SMT 1911 Mar 11 0:01 # Saigon MT? - 7:00 - ICT 1912 May - 8:00 - ICT 1931 May - 7:00 - ICT +# See Asia/Bangkok. + # China @@ -916,6 +913,10 @@ # Indonesia # +# From Paul Eggert (2014-09-06): +# The 1876 Report of the Secretary of the [US] Navy, p 306 says that Batavia +# civil time was 7:07:12.5; round to even for Jakarta. +# # From Gwillim Law (2001-05-28), overriding Shanks & Pottenger: # http://www.sumatera-inc.com/go_to_invest/about_indonesia.asp#standtime # says that Indonesia's time zones changed on 1988-01-01. Looking at some @@ -1733,12 +1734,8 @@ 3:00 - AST # Laos -# Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Asia/Vientiane 6:50:24 - LMT 1906 Jun 9 # or Viangchan - 7:06:20 - SMT 1911 Mar 11 0:01 # Saigon MT? - 7:00 - ICT 1912 May - 8:00 - ICT 1931 May - 7:00 - ICT +# See Asia/Bangkok. + # Lebanon # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S @@ -2751,6 +2748,8 @@ Zone Asia/Bangkok 6:42:04 - LMT 1880 6:42:04 - BMT 1920 Apr # Bangkok Mean Time 7:00 - ICT +Link Asia/Bangkok Asia/Phnom_Penh # Cambodia +Link Asia/Bangkok Asia/Vientiane # Laos # Turkmenistan # From Shanks & Pottenger. @@ -2788,22 +2787,65 @@ # Vietnam -# From Paul Eggert (2013-02-21): +# From Paul Eggert (2014-10-04): # Milne gives 7:16:56 for the meridian of Saigon in 1899, as being # used in Lower Laos, Cambodia, and Annam. But this is quite a ways # from Saigon's location. For now, ignore this and stick with Shanks -# and Pottenger. +# and Pottenger for LMT before 1906. # From Arthur David Olson (2008-03-18): # The English-language name of Vietnam's most populous city is "Ho Chi Minh # City"; use Ho_Chi_Minh below to avoid a name of more than 14 characters. -# From Shanks & Pottenger: +# From Paul Eggert (2014-10-21) after a heads-up from Trần Ngọc Quân: +# Trần Tiến Bình's authoritative book "Lịch Việt Nam: thế kỷ XX-XXI (1901-2100)" +# (Nhà xuất bản Văn Hoá - Thông Tin, Hanoi, 2005), pp 49-50, +# is quoted verbatim in: +# http://www.thoigian.com.vn/?mPage=P80D01 +# is translated by Brian Inglis in: +# http://mm.icann.org/pipermail/tz/2014-October/021654.html +# and is the basis for the information below. +# +# The 1906 transition was effective July 1 and standardized Indochina to +# Phù Liễn Observatory, legally 104 deg. 17'17" east of Paris. +# It's unclear whether this meant legal Paris Mean Time (00:09:21) or +# the Paris Meridian (2 deg. 20'14.03" E); the former yields 07:06:30.1333... +# and the latter 07:06:29.333... so either way it rounds to 07:06:30, +# which is used below even though the modern-day Phù Liễn Observatory +# is closer to 07:06:31. Abbreviate Phù Liễn Mean Time as PLMT. +# +# The following transitions occurred in Indochina in general (before 1954) +# and in South Vietnam in particular (after 1954): +# To 07:00 on 1911-05-01. +# To 08:00 on 1942-12-31 at 23:00. +# To 09:00 in 1945-03-14 at 23:00. +# To 07:00 on 1945-09-02 in Vietnam. +# To 08:00 on 1947-04-01 in French-controlled Indochina. +# To 07:00 on 1955-07-01 in South Vietnam. +# To 08:00 on 1959-12-31 at 23:00 in South Vietnam. +# To 07:00 on 1975-06-13 in South Vietnam. +# +# Trần cites the following sources; it's unclear which supplied the info above. +# +# Hoàng Xuân Hãn: "Lịch và lịch Việt Nam". Tập san Khoa học Xã hội, +# No. 9, Paris, February 1982. +# +# Lê Thành Lân: "Lịch và niên biểu lịch sử hai mươi thế kỷ (0001-2010)", +# NXB Thống kê, Hanoi, 2000. +# +# Lê Thành Lân: "Lịch hai thế kỷ (1802-2010) và các lịch vĩnh cửu", +# NXB Thuận Hoá, Huế, 1995. + # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Asia/Ho_Chi_Minh 7:06:40 - LMT 1906 Jun 9 - 7:06:20 - SMT 1911 Mar 11 0:01 # Saigon MT? - 7:00 - ICT 1912 May - 8:00 - ICT 1931 May +Zone Asia/Ho_Chi_Minh 7:06:40 - LMT 1906 Jul 1 + 7:06:30 - PLMT 1911 May 1 + 7:00 - ICT 1942 Dec 31 23:00 + 8:00 - IDT 1945 Mar 14 23:00 + 9:00 - JST 1945 Sep 2 + 7:00 - ICT 1947 Apr 1 + 8:00 - IDT 1955 Jul 1 + 7:00 - ICT 1959 Dec 31 23:00 + 8:00 - IDT 1975 Jun 13 7:00 - ICT # Yemen
--- a/jdk/make/data/tzdata/australasia Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/make/data/tzdata/australasia Wed Jul 05 20:05:54 2017 +0200 @@ -354,20 +354,27 @@ # Fiji will end DST on 2014-01-19 02:00: # http://www.fiji.gov.fj/Media-Center/Press-Releases/DAYLIGHT-SAVINGS-TO-END-THIS-MONTH-%281%29.aspx -# From Paul Eggert (2014-01-10): -# For now, guess that Fiji springs forward the Sunday before the fourth -# Monday in October, and springs back the penultimate Sunday in January. -# This is ad hoc, but matches recent practice. +# From Ken Rylander (2014-10-20): +# DST will start Nov. 2 this year. +# http://www.fiji.gov.fj/Media-Center/Press-Releases/DAYLIGHT-SAVING-STARTS-ON-SUNDAY,-NOVEMBER-2ND.aspx + +# From Paul Eggert (2014-10-20): +# For now, guess DST from 02:00 the first Sunday in November to +# 03:00 the first Sunday on or after January 18. Although ad hoc, it +# matches this year's plan and seems more likely to match future +# practice than guessing no DST. # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Fiji 1998 1999 - Nov Sun>=1 2:00 1:00 S Rule Fiji 1999 2000 - Feb lastSun 3:00 0 - Rule Fiji 2009 only - Nov 29 2:00 1:00 S Rule Fiji 2010 only - Mar lastSun 3:00 0 - -Rule Fiji 2010 max - Oct Sun>=21 2:00 1:00 S +Rule Fiji 2010 2013 - Oct Sun>=21 2:00 1:00 S Rule Fiji 2011 only - Mar Sun>=1 3:00 0 - Rule Fiji 2012 2013 - Jan Sun>=18 3:00 0 - -Rule Fiji 2014 max - Jan Sun>=18 2:00 0 - +Rule Fiji 2014 only - Jan Sun>=18 2:00 0 - +Rule Fiji 2014 max - Nov Sun>=1 2:00 1:00 S +Rule Fiji 2015 max - Jan Sun>=18 3:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Pacific/Fiji 11:55:44 - LMT 1915 Oct 26 # Suva 12:00 Fiji FJ%sT # Fiji Time @@ -542,6 +549,30 @@ Zone Pacific/Port_Moresby 9:48:40 - LMT 1880 9:48:32 - PMMT 1895 # Port Moresby Mean Time 10:00 - PGT # Papua New Guinea Time +# +# From Paul Eggert (2014-10-13): +# Base the Bougainville entry on the Arawa-Kieta region, which appears to have +# the most people even though it was devastated in the Bougainville Civil War. +# +# Although Shanks gives 1942-03-15 / 1943-11-01 for JST, these dates +# are apparently rough guesswork from the starts of military campaigns. +# The World War II entries below are instead based on Arawa-Kieta. +# The Japanese occupied Kieta in July 1942, +# according to the Pacific War Online Encyclopedia +# http://pwencycl.kgbudge.com/B/o/Bougainville.htm +# and seem to have controlled it until their 1945-08-21 surrender. +# +# The Autonomous Region of Bougainville plans to switch from UTC+10 to UTC+11 +# on 2014-12-28 at 02:00. They call UTC+11 "Bougainville Standard Time"; +# abbreviate this as BST. See: +# http://www.bougainville24.com/bougainville-issues/bougainville-gets-own-timezone/ +# +Zone Pacific/Bougainville 10:22:16 - LMT 1880 + 9:48:32 - PMMT 1895 + 10:00 - PGT 1942 Jul + 9:00 - JST 1945 Aug 21 + 10:00 - PGT 2014 Dec 28 2:00 + 11:00 - BST # Pitcairn # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -826,6 +857,7 @@ # 10:00 AEST AEDT Eastern Australia # 10:00 ChST Chamorro # 10:30 LHST LHDT Lord Howe* +# 11:00 BST Bougainville* # 11:30 NZMT NZST New Zealand through 1945 # 12:00 NZST NZDT New Zealand 1946-present # 12:15 CHAST Chatham through 1945*
--- a/jdk/make/data/tzdata/europe Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/make/data/tzdata/europe Wed Jul 05 20:05:54 2017 +0200 @@ -91,10 +91,11 @@ # 0:00 WET WEST WEMT Western Europe # 0:19:32.13 AMT NST Amsterdam, Netherlands Summer (1835-1937)* # 0:20 NET NEST Netherlands (1937-1940)* +# 1:00 BST British Standard (1968-1971) # 1:00 CET CEST CEMT Central Europe # 1:00:14 SET Swedish (1879-1899)* # 2:00 EET EEST Eastern Europe -# 3:00 FET Further-eastern Europe* +# 3:00 FET Further-eastern Europe (2011-2014)* # 3:00 MSK MSD MSM* Moscow # From Peter Ilieve (1994-12-04), @@ -746,6 +747,13 @@ # http://www.belta.by/ru/all_news/society/V-Belarusi-otmenjaetsja-perexod-na-sezonnoe-vremja_i_572952.html # http://naviny.by/rubrics/society/2011/09/16/ic_articles_116_175144/ # http://news.tut.by/society/250578.html +# +# From Alexander Bokovoy (2014-10-09): +# Belarussian government decided against changing to winter time.... +# http://eng.belta.by/all_news/society/Belarus-decides-against-adjusting-time-in-Russias-wake_i_76335.html +# From Paul Eggert (2014-10-08): +# Hence Belarus can share time zone abbreviations with Moscow again. +# # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Europe/Minsk 1:50:16 - LMT 1880 1:50 - MMT 1924 May 2 # Minsk Mean Time @@ -758,7 +766,8 @@ 2:00 - EET 1992 Mar 29 0:00s 2:00 1:00 EEST 1992 Sep 27 0:00s 2:00 Russia EE%sT 2011 Mar 27 2:00s - 3:00 - FET + 3:00 - FET 2014 Oct 26 1:00s + 3:00 - MSK # Belgium # @@ -2524,7 +2533,7 @@ # The Kemerovo region will remain at UTC+7 through the 2014-10-26 change, thus # realigning itself with KRAT. -Zone Asia/Novokuznetsk 5:48:48 - NMT 1920 Jan 6 +Zone Asia/Novokuznetsk 5:48:48 - LMT 1924 May 1 6:00 - KRAT 1930 Jun 21 # Krasnoyarsk Time 7:00 Russia KRA%sT 1991 Mar 31 2:00s 6:00 Russia KRA%sT 1992 Jan 19 2:00s
--- a/jdk/make/data/tzdata/northamerica Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/make/data/tzdata/northamerica Wed Jul 05 20:05:54 2017 +0200 @@ -300,6 +300,12 @@ # time zone, but we do go by the Eastern time zone because so many people work # in Columbus." +# From Paul Eggert (2014-09-06): +# Monthly Notices of the Royal Astronomical Society 44, 4 (1884-02-08), 208 +# says that New York City Hall time was 3 minutes 58.4 seconds fast of +# Eastern time (i.e., -4:56:01.6) just before the 1883 switch. Round to the +# nearest second. + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER Rule NYC 1920 only - Mar lastSun 2:00 1:00 D Rule NYC 1920 only - Oct lastSun 2:00 0 S @@ -1118,17 +1124,16 @@ # An amendment to the Interpretation Act was registered on February 19/2007.... # http://action.attavik.ca/home/justice-gn/attach/2007/gaz02part2.pdf -# From Paul Eggert (2006-04-25): +# From Paul Eggert (2014-10-18): # H. David Matthews and Mary Vincent's map # "It's about TIME", _Canadian Geographic_ (September-October 1998) -# http://www.canadiangeographic.ca/Magazine/SO98/geomap.asp +# http://www.canadiangeographic.ca/Magazine/SO98/alacarte.asp # contains detailed boundaries for regions observing nonstandard # time and daylight saving time arrangements in Canada circa 1998. # -# INMS, the Institute for National Measurement Standards in Ottawa, has -# information about standard and daylight saving time zones in Canada. -# http://inms-ienm.nrc-cnrc.gc.ca/en/time_services/daylight_saving_e.php -# (updated periodically). +# National Research Council Canada maintains info about time zones and DST. +# http://www.nrc-cnrc.gc.ca/eng/services/time/time_zones.html +# http://www.nrc-cnrc.gc.ca/eng/services/time/faq/index.html#Q5 # Its unofficial information is often taken from Matthews and Vincent. # From Paul Eggert (2006-06-27): @@ -1993,10 +1998,7 @@ # [Also see <http://www.nunatsiaq.com/nunavut/nvt10309_06.html> (2001-03-09).] # From Gwillim Law (2005-05-21): -# According to maps at -# http://inms-ienm.nrc-cnrc.gc.ca/images/time_services/TZ01SWE.jpg -# http://inms-ienm.nrc-cnrc.gc.ca/images/time_services/TZ01SSE.jpg -# (both dated 2003), and +# According to ... # http://www.canadiangeographic.ca/Magazine/SO98/geomap.asp # (from a 1998 Canadian Geographic article), the de facto and de jure time # for Southampton Island (at the north end of Hudson Bay) is UTC-5 all year @@ -2005,9 +2007,11 @@ # predates the creation of Nunavut, it probably goes back many years.... # The Inuktitut name of Coral Harbour is Sallit, but it's rarely used. # -# From Paul Eggert (2005-07-26): +# From Paul Eggert (2014-10-17): # For lack of better information, assume that Southampton Island observed -# daylight saving only during wartime. +# daylight saving only during wartime. Gwillim Law's email also +# mentioned maps now maintained by National Research Council Canada; +# see above for an up-to-date link. # From Chris Walton (2007-03-01): # ... the community of Resolute (located on Cornwallis Island in @@ -3008,10 +3012,21 @@ # Shanks & Pottenger give -5:07:12, but Milne records -5:07:10.41 from an # unspecified official document, and says "This time is used throughout the # island". Go with Milne. Round to the nearest second as required by zic. +# +# Shanks & Pottenger give April 28 for the 1974 spring-forward transition, but +# Lance Neita writes that Prime Minister Michael Manley decreed it January 5. +# Assume Neita meant Jan 6 02:00, the same as the US. Neita also writes that +# Manley's supporters associated this act with Manley's nickname "Joshua" +# (recall that in the Bible the sun stood still at Joshua's request), +# and with the Rod of Correction which Manley said he had received from +# Haile Selassie, Emperor of Ethiopia. See: +# Neita L. The politician in all of us. Jamaica Observer 2014-09-20 +# http://www.jamaicaobserver.com/columns/The-politician-in-all-of-us_17573647 +# # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone America/Jamaica -5:07:11 - LMT 1890 # Kingston -5:07:11 - KMT 1912 Feb # Kingston Mean Time - -5:00 - EST 1974 Apr 28 2:00 + -5:00 - EST 1974 -5:00 US E%sT 1984 -5:00 - EST
--- a/jdk/make/data/tzdata/zone.tab Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/make/data/tzdata/zone.tab Wed Jul 05 20:05:54 2017 +0200 @@ -330,7 +330,8 @@ PF -1732-14934 Pacific/Tahiti Society Islands PF -0900-13930 Pacific/Marquesas Marquesas Islands PF -2308-13457 Pacific/Gambier Gambier Islands -PG -0930+14710 Pacific/Port_Moresby +PG -0930+14710 Pacific/Port_Moresby most locations +PG -0613+15534 Pacific/Bougainville Bougainville PH +1435+12100 Asia/Manila PK +2452+06703 Asia/Karachi PL +5215+02100 Europe/Warsaw
--- a/jdk/make/mapfiles/libjava/mapfile-vers Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/make/mapfiles/libjava/mapfile-vers Wed Jul 05 20:05:54 2017 +0200 @@ -75,6 +75,7 @@ Java_java_io_FileDescriptor_initIDs; Java_java_io_FileDescriptor_sync; + Java_java_io_FileDescriptor_getAppend; Java_java_io_FileInputStream_available; Java_java_io_FileInputStream_close0; Java_java_io_FileInputStream_initIDs;
--- a/jdk/make/profile-includes.txt Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/make/profile-includes.txt Wed Jul 05 20:05:54 2017 +0200 @@ -54,14 +54,12 @@ $(OPENJDK_TARGET_CPU_LEGACY_LIB)/server/$(LIBRARY_PREFIX)jvm$(SHARED_LIBRARY_SUFFIX) \ $(OPENJDK_TARGET_CPU_LEGACY_LIB)/server/$(LIBRARY_PREFIX)jvm.diz \ $(OPENJDK_TARGET_CPU_LEGACY_LIB)/server/Xusage.txt \ - calendars.properties \ classlist \ ext/localedata.jar \ ext/meta-index \ ext/sunec.jar \ ext/sunjce_provider.jar \ ext/sunpkcs11.jar \ - hijrah-config-umalqura.properties \ jce.jar \ jsse.jar \ logging.properties \
--- a/jdk/src/java.base/share/classes/java/io/File.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/java/io/File.java Wed Jul 05 20:05:54 2017 +0200 @@ -1588,7 +1588,7 @@ /** * A convenience method to set the owner's read permission for this abstract * pathname. On some platforms it may be possible to start the Java virtual - * machine with special privileges that allow it to read files that that are + * machine with special privileges that allow it to read files that are * marked as unreadable. * * <p>An invocation of this method of the form <tt>file.setReadable(arg)</tt>
--- a/jdk/src/java.base/share/classes/java/io/FileOutputStream.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/java/io/FileOutputStream.java Wed Jul 05 20:05:54 2017 +0200 @@ -26,6 +26,8 @@ package java.io; import java.nio.channels.FileChannel; +import sun.misc.SharedSecrets; +import sun.misc.JavaIOFileDescriptorAccess; import sun.nio.ch.FileChannelImpl; @@ -53,16 +55,17 @@ class FileOutputStream extends OutputStream { /** + * Access to FileDescriptor internals. + */ + private static final JavaIOFileDescriptorAccess fdAccess = + SharedSecrets.getJavaIOFileDescriptorAccess(); + + /** * The system dependent file descriptor. */ private final FileDescriptor fd; /** - * True if the file is opened for append. - */ - private final boolean append; - - /** * The associated channel, initialized lazily. */ private FileChannel channel; @@ -207,7 +210,6 @@ } this.fd = new FileDescriptor(); fd.attach(this); - this.append = append; this.path = name; open(name, append); @@ -245,7 +247,6 @@ security.checkWrite(fdObj); } this.fd = fdObj; - this.append = false; this.path = null; fd.attach(this); @@ -287,7 +288,7 @@ * @exception IOException if an I/O error occurs. */ public void write(int b) throws IOException { - write(b, append); + write(b, fdAccess.getAppend(fd)); } /** @@ -310,7 +311,7 @@ * @exception IOException if an I/O error occurs. */ public void write(byte b[]) throws IOException { - writeBytes(b, 0, b.length, append); + writeBytes(b, 0, b.length, fdAccess.getAppend(fd)); } /** @@ -323,7 +324,7 @@ * @exception IOException if an I/O error occurs. */ public void write(byte b[], int off, int len) throws IOException { - writeBytes(b, off, len, append); + writeBytes(b, off, len, fdAccess.getAppend(fd)); } /** @@ -395,7 +396,7 @@ public FileChannel getChannel() { synchronized (this) { if (channel == null) { - channel = FileChannelImpl.open(fd, path, false, true, append, this); + channel = FileChannelImpl.open(fd, path, false, true, this); } return channel; }
--- a/jdk/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java Wed Jul 05 20:05:54 2017 +0200 @@ -44,6 +44,10 @@ super(type, chooseDelegatingForm(target)); } + protected DelegatingMethodHandle(MethodType type, LambdaForm form) { + super(type, form); + } + /** Define this to extract the delegated target which supplies the invocation behavior. */ abstract protected MethodHandle getTarget(); @@ -88,14 +92,31 @@ return makeReinvokerForm(target, MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, NF_getTarget); } + static LambdaForm makeReinvokerForm(MethodHandle target, + int whichCache, + Object constraint, + NamedFunction getTargetFn) { + String debugString; + switch(whichCache) { + case MethodTypeForm.LF_REBIND: debugString = "BMH.reinvoke"; break; + case MethodTypeForm.LF_DELEGATE: debugString = "MH.delegate"; break; + default: debugString = "MH.reinvoke"; break; + } + // No pre-action needed. + return makeReinvokerForm(target, whichCache, constraint, debugString, true, getTargetFn, null); + } /** Create a LF which simply reinvokes a target of the given basic type. */ static LambdaForm makeReinvokerForm(MethodHandle target, int whichCache, Object constraint, - NamedFunction getTargetFn) { + String debugString, + boolean forceInline, + NamedFunction getTargetFn, + NamedFunction preActionFn) { MethodType mtype = target.type().basicType(); boolean customized = (whichCache < 0 || mtype.parameterSlotCount() > MethodType.MAX_MH_INVOKER_ARITY); + boolean hasPreAction = (preActionFn != null); LambdaForm form; if (!customized) { form = mtype.form().cachedLambdaForm(whichCache); @@ -105,12 +126,16 @@ final int ARG_BASE = 1; final int ARG_LIMIT = ARG_BASE + mtype.parameterCount(); int nameCursor = ARG_LIMIT; + final int PRE_ACTION = hasPreAction ? nameCursor++ : -1; final int NEXT_MH = customized ? -1 : nameCursor++; final int REINVOKE = nameCursor++; LambdaForm.Name[] names = LambdaForm.arguments(nameCursor - ARG_LIMIT, mtype.invokerType()); assert(names.length == nameCursor); names[THIS_DMH] = names[THIS_DMH].withConstraint(constraint); Object[] targetArgs; + if (hasPreAction) { + names[PRE_ACTION] = new LambdaForm.Name(preActionFn, names[THIS_DMH]); + } if (customized) { targetArgs = Arrays.copyOfRange(names, ARG_BASE, ARG_LIMIT, Object[].class); names[REINVOKE] = new LambdaForm.Name(target, targetArgs); // the invoker is the target itself @@ -120,20 +145,14 @@ targetArgs[0] = names[NEXT_MH]; // overwrite this MH with next MH names[REINVOKE] = new LambdaForm.Name(mtype, targetArgs); } - String debugString; - switch(whichCache) { - case MethodTypeForm.LF_REBIND: debugString = "BMH.reinvoke"; break; - case MethodTypeForm.LF_DELEGATE: debugString = "MH.delegate"; break; - default: debugString = "MH.reinvoke"; break; - } - form = new LambdaForm(debugString, ARG_LIMIT, names); + form = new LambdaForm(debugString, ARG_LIMIT, names, forceInline); if (!customized) { form = mtype.form().setCachedLambdaForm(whichCache, form); } return form; } - private static final NamedFunction NF_getTarget; + static final NamedFunction NF_getTarget; static { try { NF_getTarget = new NamedFunction(DelegatingMethodHandle.class
--- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Wed Jul 05 20:05:54 2017 +0200 @@ -628,8 +628,13 @@ // Mark this method as a compiled LambdaForm mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Compiled;", true); - // Force inlining of this invoker method. - mv.visitAnnotation("Ljava/lang/invoke/ForceInline;", true); + if (lambdaForm.forceInline) { + // Force inlining of this invoker method. + mv.visitAnnotation("Ljava/lang/invoke/ForceInline;", true); + } else { + mv.visitAnnotation("Ljava/lang/invoke/DontInline;", true); + } + // iterate over the form's names, generating bytecode instructions for each // start iterating at the first name following the arguments
--- a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java Wed Jul 05 20:05:54 2017 +0200 @@ -119,6 +119,7 @@ class LambdaForm { final int arity; final int result; + final boolean forceInline; @Stable final Name[] names; final String debugName; MemberName vmentry; // low-level behavior, or null if not yet prepared @@ -243,11 +244,16 @@ LambdaForm(String debugName, int arity, Name[] names, int result) { + this(debugName, arity, names, result, true); + } + LambdaForm(String debugName, + int arity, Name[] names, int result, boolean forceInline) { assert(namesOK(arity, names)); this.arity = arity; this.result = fixResult(result, names); this.names = names.clone(); this.debugName = fixDebugName(debugName); + this.forceInline = forceInline; int maxOutArity = normalize(); if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) { // Cannot use LF interpreter on very high arity expressions. @@ -255,17 +261,23 @@ compileToBytecode(); } } - LambdaForm(String debugName, int arity, Name[] names) { - this(debugName, - arity, names, LAST_RESULT); + this(debugName, arity, names, LAST_RESULT, true); } - + LambdaForm(String debugName, + int arity, Name[] names, boolean forceInline) { + this(debugName, arity, names, LAST_RESULT, forceInline); + } LambdaForm(String debugName, Name[] formals, Name[] temps, Name result) { this(debugName, - formals.length, buildNames(formals, temps, result), LAST_RESULT); + formals.length, buildNames(formals, temps, result), LAST_RESULT, true); + } + LambdaForm(String debugName, + Name[] formals, Name[] temps, Name result, boolean forceInline) { + this(debugName, + formals.length, buildNames(formals, temps, result), LAST_RESULT, forceInline); } private static Name[] buildNames(Name[] formals, Name[] temps, Name result) { @@ -279,6 +291,10 @@ } private LambdaForm(String sig) { + this(sig, true); + } + + private LambdaForm(String sig, boolean forceInline) { // Make a blank lambda form, which returns a constant zero or null. // It is used as a template for managing the invocation of similar forms that are non-empty. // Called only from getPreparedForm. @@ -287,6 +303,7 @@ this.result = (signatureReturn(sig) == V_TYPE ? -1 : arity); this.names = buildEmptyNames(arity, sig); this.debugName = "LF.zero"; + this.forceInline = forceInline; assert(nameRefsAreLegal()); assert(isEmpty()); assert(sig.equals(basicTypeSignature())) : sig + " != " + basicTypeSignature();
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java Wed Jul 05 20:05:54 2017 +0200 @@ -1438,10 +1438,9 @@ /*non-public*/ void updateForm(LambdaForm newForm) { if (form == newForm) return; - assert(this instanceof DirectMethodHandle && this.internalMemberName().isStatic()); - // ISSUE: Should we have a memory fence here? + newForm.prepare(); // as in MethodHandle.<init> UNSAFE.putObject(this, FORM_OFFSET, newForm); - this.form.prepare(); // as in MethodHandle.<init> + UNSAFE.fullFence(); } private static final long FORM_OFFSET;
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Jul 05 20:05:54 2017 +0200 @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.function.Function; import sun.invoke.empty.Empty; import sun.invoke.util.ValueConversions; @@ -713,10 +714,11 @@ LambdaForm form = makeGuardWithTestForm(basicType); BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL(); BoundMethodHandle mh; + try { mh = (BoundMethodHandle) data.constructor().invokeBasic(type, form, - (Object) test, (Object) target, (Object) fallback); + (Object) test, (Object) profile(target), (Object) profile(fallback)); } catch (Throwable ex) { throw uncaughtException(ex); } @@ -724,6 +726,129 @@ return mh; } + + static + MethodHandle profile(MethodHandle target) { + if (DONT_INLINE_THRESHOLD >= 0) { + return makeBlockInlningWrapper(target); + } else { + return target; + } + } + + /** + * Block inlining during JIT-compilation of a target method handle if it hasn't been invoked enough times. + * Corresponding LambdaForm has @DontInline when compiled into bytecode. + */ + static + MethodHandle makeBlockInlningWrapper(MethodHandle target) { + LambdaForm lform = PRODUCE_BLOCK_INLINING_FORM.apply(target); + return new CountingWrapper(target, lform, + PRODUCE_BLOCK_INLINING_FORM, PRODUCE_REINVOKER_FORM, + DONT_INLINE_THRESHOLD); + } + + /** Constructs reinvoker lambda form which block inlining during JIT-compilation for a particular method handle */ + private static final Function<MethodHandle, LambdaForm> PRODUCE_BLOCK_INLINING_FORM = new Function<MethodHandle, LambdaForm>() { + @Override + public LambdaForm apply(MethodHandle target) { + return DelegatingMethodHandle.makeReinvokerForm(target, + MethodTypeForm.LF_DELEGATE_BLOCK_INLINING, CountingWrapper.class, "reinvoker.dontInline", false, + DelegatingMethodHandle.NF_getTarget, CountingWrapper.NF_maybeStopCounting); + } + }; + + /** Constructs simple reinvoker lambda form for a particular method handle */ + private static final Function<MethodHandle, LambdaForm> PRODUCE_REINVOKER_FORM = new Function<MethodHandle, LambdaForm>() { + @Override + public LambdaForm apply(MethodHandle target) { + return DelegatingMethodHandle.makeReinvokerForm(target, + MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, DelegatingMethodHandle.NF_getTarget); + } + }; + + /** + * Counting method handle. It has 2 states: counting and non-counting. + * It is in counting state for the first n invocations and then transitions to non-counting state. + * Behavior in counting and non-counting states is determined by lambda forms produced by + * countingFormProducer & nonCountingFormProducer respectively. + */ + static class CountingWrapper extends DelegatingMethodHandle { + private final MethodHandle target; + private int count; + private Function<MethodHandle, LambdaForm> countingFormProducer; + private Function<MethodHandle, LambdaForm> nonCountingFormProducer; + private volatile boolean isCounting; + + private CountingWrapper(MethodHandle target, LambdaForm lform, + Function<MethodHandle, LambdaForm> countingFromProducer, + Function<MethodHandle, LambdaForm> nonCountingFormProducer, + int count) { + super(target.type(), lform); + this.target = target; + this.count = count; + this.countingFormProducer = countingFromProducer; + this.nonCountingFormProducer = nonCountingFormProducer; + this.isCounting = (count > 0); + } + + @Hidden + @Override + protected MethodHandle getTarget() { + return target; + } + + @Override + public MethodHandle asTypeUncached(MethodType newType) { + MethodHandle newTarget = target.asType(newType); + MethodHandle wrapper; + if (isCounting) { + LambdaForm lform; + lform = countingFormProducer.apply(target); + wrapper = new CountingWrapper(newTarget, lform, countingFormProducer, nonCountingFormProducer, DONT_INLINE_THRESHOLD); + } else { + wrapper = newTarget; // no need for a counting wrapper anymore + } + return (asTypeCache = wrapper); + } + + boolean countDown() { + if (count <= 0) { + // Try to limit number of updates. MethodHandle.updateForm() doesn't guarantee LF update visibility. + if (isCounting) { + isCounting = false; + return true; + } else { + return false; + } + } else { + --count; + return false; + } + } + + @Hidden + static void maybeStopCounting(Object o1) { + CountingWrapper wrapper = (CountingWrapper) o1; + if (wrapper.countDown()) { + // Reached invocation threshold. Replace counting behavior with a non-counting one. + LambdaForm lform = wrapper.nonCountingFormProducer.apply(wrapper.target); + lform.compileToBytecode(); // speed up warmup by avoiding LF interpretation again after transition + wrapper.updateForm(lform); + } + } + + static final NamedFunction NF_maybeStopCounting; + static { + Class<?> THIS_CLASS = CountingWrapper.class; + try { + NF_maybeStopCounting = new NamedFunction(THIS_CLASS.getDeclaredMethod("maybeStopCounting", Object.class)); + } catch (ReflectiveOperationException ex) { + throw newInternalError(ex); + } + } + } + static LambdaForm makeGuardWithTestForm(MethodType basicType) { LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWT);
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java Wed Jul 05 20:05:54 2017 +0200 @@ -47,10 +47,11 @@ static final boolean TRACE_METHOD_LINKAGE; static final boolean USE_LAMBDA_FORM_EDITOR; static final int COMPILE_THRESHOLD; + static final int DONT_INLINE_THRESHOLD; static final int PROFILE_LEVEL; static { - final Object[] values = { false, false, false, false, false, null, null }; + final Object[] values = new Object[8]; AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES"); @@ -59,7 +60,8 @@ values[3] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE"); values[4] = Boolean.getBoolean("java.lang.invoke.MethodHandle.USE_LF_EDITOR"); values[5] = Integer.getInteger("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", 30); - values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0); + values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.DONT_INLINE_THRESHOLD", 30); + values[7] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0); return null; } }); @@ -69,7 +71,8 @@ TRACE_METHOD_LINKAGE = (Boolean) values[3]; USE_LAMBDA_FORM_EDITOR = (Boolean) values[4]; COMPILE_THRESHOLD = (Integer) values[5]; - PROFILE_LEVEL = (Integer) values[6]; + DONT_INLINE_THRESHOLD = (Integer) values[6]; + PROFILE_LEVEL = (Integer) values[7]; } /** Tell if any of the debugging switches are turned on.
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java Wed Jul 05 20:05:54 2017 +0200 @@ -63,24 +63,25 @@ final @Stable LambdaForm[] lambdaForms; // Indexes into lambdaForms: static final int - LF_INVVIRTUAL = 0, // DMH invokeVirtual - LF_INVSTATIC = 1, - LF_INVSPECIAL = 2, - LF_NEWINVSPECIAL = 3, - LF_INVINTERFACE = 4, - LF_INVSTATIC_INIT = 5, // DMH invokeStatic with <clinit> barrier - LF_INTERPRET = 6, // LF interpreter - LF_REBIND = 7, // BoundMethodHandle - LF_DELEGATE = 8, // DelegatingMethodHandle - LF_EX_LINKER = 9, // invokeExact_MT (for invokehandle) - LF_EX_INVOKER = 10, // MHs.invokeExact - LF_GEN_LINKER = 11, // generic invoke_MT (for invokehandle) - LF_GEN_INVOKER = 12, // generic MHs.invoke - LF_CS_LINKER = 13, // linkToCallSite_CS - LF_MH_LINKER = 14, // linkToCallSite_MH - LF_GWC = 15, // guardWithCatch (catchException) - LF_GWT = 16, // guardWithTest - LF_LIMIT = 17; + LF_INVVIRTUAL = 0, // DMH invokeVirtual + LF_INVSTATIC = 1, + LF_INVSPECIAL = 2, + LF_NEWINVSPECIAL = 3, + LF_INVINTERFACE = 4, + LF_INVSTATIC_INIT = 5, // DMH invokeStatic with <clinit> barrier + LF_INTERPRET = 6, // LF interpreter + LF_REBIND = 7, // BoundMethodHandle + LF_DELEGATE = 8, // DelegatingMethodHandle + LF_DELEGATE_BLOCK_INLINING = 9, // Counting DelegatingMethodHandle w/ @DontInline + LF_EX_LINKER = 10, // invokeExact_MT (for invokehandle) + LF_EX_INVOKER = 11, // MHs.invokeExact + LF_GEN_LINKER = 12, // generic invoke_MT (for invokehandle) + LF_GEN_INVOKER = 13, // generic MHs.invoke + LF_CS_LINKER = 14, // linkToCallSite_CS + LF_MH_LINKER = 15, // linkToCallSite_MH + LF_GWC = 16, // guardWithCatch (catchException) + LF_GWT = 17, // guardWithTest + LF_LIMIT = 18; /** Return the type corresponding uniquely (1-1) to this MT-form. * It might have any primitive returns or arguments, but will have no references except Object.
--- a/jdk/src/java.base/share/classes/java/nio/Buffer.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/java/nio/Buffer.java Wed Jul 05 20:05:54 2017 +0200 @@ -239,7 +239,7 @@ * @throws IllegalArgumentException * If the preconditions on <tt>newPosition</tt> do not hold */ - public final Buffer position(int newPosition) { + public Buffer position(int newPosition) { if ((newPosition > limit) || (newPosition < 0)) throw new IllegalArgumentException(); position = newPosition; @@ -270,7 +270,7 @@ * @throws IllegalArgumentException * If the preconditions on <tt>newLimit</tt> do not hold */ - public final Buffer limit(int newLimit) { + public Buffer limit(int newLimit) { if ((newLimit > capacity) || (newLimit < 0)) throw new IllegalArgumentException(); limit = newLimit; @@ -284,7 +284,7 @@ * * @return This buffer */ - public final Buffer mark() { + public Buffer mark() { mark = position; return this; } @@ -300,7 +300,7 @@ * @throws InvalidMarkException * If the mark has not been set */ - public final Buffer reset() { + public Buffer reset() { int m = mark; if (m < 0) throw new InvalidMarkException(); @@ -325,7 +325,7 @@ * * @return This buffer */ - public final Buffer clear() { + public Buffer clear() { position = 0; limit = capacity; mark = -1; @@ -353,7 +353,7 @@ * * @return This buffer */ - public final Buffer flip() { + public Buffer flip() { limit = position; position = 0; mark = -1; @@ -375,7 +375,7 @@ * * @return This buffer */ - public final Buffer rewind() { + public Buffer rewind() { position = 0; mark = -1; return this;
--- a/jdk/src/java.base/share/classes/java/nio/MappedByteBuffer.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/java/nio/MappedByteBuffer.java Wed Jul 05 20:05:54 2017 +0200 @@ -208,4 +208,76 @@ private native boolean isLoaded0(long address, long length, int pageCount); private native void load0(long address, long length); private native void force0(FileDescriptor fd, long address, long length); + + // -- Covariant return type overrides + + /** + * {@inheritDoc} + * @since 1.9 + */ + @Override + public final MappedByteBuffer position(int newPosition) { + super.position(newPosition); + return this; + } + + /** + * {@inheritDoc} + * @since 1.9 + */ + @Override + public final MappedByteBuffer limit(int newLimit) { + super.limit(newLimit); + return this; + } + + /** + * {@inheritDoc} + * @since 1.9 + */ + @Override + public final MappedByteBuffer mark() { + super.mark(); + return this; + } + + /** + * {@inheritDoc} + * @since 1.9 + */ + @Override + public final MappedByteBuffer reset() { + super.reset(); + return this; + } + + /** + * {@inheritDoc} + * @since 1.9 + */ + @Override + public final MappedByteBuffer clear() { + super.clear(); + return this; + } + + /** + * {@inheritDoc} + * @since 1.9 + */ + @Override + public final MappedByteBuffer flip() { + super.flip(); + return this; + } + + /** + * {@inheritDoc} + * @since 1.9 + */ + @Override + public final MappedByteBuffer rewind() { + super.rewind(); + return this; + } }
--- a/jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template Wed Jul 05 20:05:54 2017 +0200 @@ -1025,6 +1025,106 @@ return offset; } + // -- Covariant return type overrides + + /** + * {@inheritDoc} + * @since 1.9 + */ + @Override + public +#if[!byte] + final +#end[!byte] + $Type$Buffer position(int newPosition) { + super.position(newPosition); + return this; + } + + /** + * {@inheritDoc} + * @since 1.9 + */ + @Override + public +#if[!byte] + final +#end[!byte] + $Type$Buffer limit(int newLimit) { + super.limit(newLimit); + return this; + } + + /** + * {@inheritDoc} + * @since 1.9 + */ + @Override + public +#if[!byte] + final +#end[!byte] + $Type$Buffer mark() { + super.mark(); + return this; + } + + /** + * {@inheritDoc} + * @since 1.9 + */ + @Override + public +#if[!byte] + final +#end[!byte] + $Type$Buffer reset() { + super.reset(); + return this; + } + + /** + * {@inheritDoc} + * @since 1.9 + */ + @Override + public +#if[!byte] + final +#end[!byte] + $Type$Buffer clear() { + super.clear(); + return this; + } + + /** + * {@inheritDoc} + * @since 1.9 + */ + @Override + public +#if[!byte] + final +#end[!byte] + $Type$Buffer flip() { + super.flip(); + return this; + } + + /** + * {@inheritDoc} + * @since 1.9 + */ + @Override + public +#if[!byte] + final +#end[!byte] + $Type$Buffer rewind() { + super.rewind(); + return this; + } + /** * Compacts this buffer <i>(optional operation)</i>. *
--- a/jdk/src/java.base/share/classes/java/nio/file/FileStore.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/java/nio/file/FileStore.java Wed Jul 05 20:05:54 2017 +0200 @@ -208,7 +208,7 @@ * @param attribute * the attribute to read - * @return the attribute value; {@code null} may be a valid for some + * @return the attribute value; {@code null} may be valid for some * attributes * * @throws UnsupportedOperationException
--- a/jdk/src/java.base/share/classes/java/nio/file/attribute/package-info.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/java/nio/file/attribute/package-info.java Wed Jul 05 20:05:54 2017 +0200 @@ -51,7 +51,7 @@ * <p> An attribute view provides a read-only or updatable view of the non-opaque * values, or <em>metadata</em>, associated with objects in a file system. * The {@link java.nio.file.attribute.FileAttributeView} interface is - * extended by several other interfaces that views to specific sets of file + * extended by several other interfaces that provide views to specific sets of file * attributes. {@code FileAttributeViews} are selected by invoking the {@link * java.nio.file.Files#getFileAttributeView} method with a * <em>type-token</em> to identify the required view. Views can also be identified
--- a/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java Wed Jul 05 20:05:54 2017 +0200 @@ -61,13 +61,14 @@ import java.io.File; import java.io.FileInputStream; +import java.io.FilePermission; import java.io.IOException; import java.io.InputStream; import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.Serializable; import java.security.AccessController; -import java.security.PrivilegedActionException; +import java.security.PrivilegedAction; import java.time.Clock; import java.time.DateTimeException; import java.time.Instant; @@ -145,29 +146,8 @@ * property resource that defines the {@code ID}, the {@code calendar type}, * the start of the calendar, the alignment with the * ISO calendar, and the length of each month for a range of years. - * The variants are identified in the {@code calendars.properties} file. - * The new properties are prefixed with {@code "calendars.hijrah."}: - * <table cellpadding="2" border="0" summary="Configuration of Hijrah Calendar Variants"> - * <thead> - * <tr class="tableSubHeadingColor"> - * <th class="colFirst" align="left">Property Name</th> - * <th class="colFirst" align="left">Property value</th> - * <th class="colLast" align="left">Description </th> - * </tr> - * </thead> - * <tbody> - * <tr class="altColor"> - * <td>calendars.hijrah.{ID}</td> - * <td>The property resource defining the {@code {ID}} variant</td> - * <td>The property resource is located with the {@code calendars.properties} file</td> - * </tr> - * <tr class="rowColor"> - * <td>calendars.hijrah.{ID}.type</td> - * <td>The calendar type</td> - * <td>LDML defines the calendar type names</td> - * </tr> - * </tbody> - * </table> + * The variants are loaded by HijrahChronology as a resource from + * hijrah-config-<calendar type>.properties. * <p> * The Hijrah property resource is a set of properties that describe the calendar. * The syntax is defined by {@code java.util.Properties#load(Reader)}. @@ -279,91 +259,41 @@ * Computed by {@link #createEpochMonths}. */ private transient int maxYearLength; - /** - * A reference to the properties stored in - * ${java.home}/lib/calendars.properties - */ - private final transient static Properties calendarProperties; /** - * Prefix of property names for Hijrah calendar variants. + * Prefix of resource names for Hijrah calendar variants. */ - private static final String PROP_PREFIX = "calendar.hijrah."; - /** - * Suffix of property names containing the calendar type of a variant. - */ - private static final String PROP_TYPE_SUFFIX = ".type"; + private static final String RESOURCE_PREFIX = "hijrah-config-"; /** - * Static initialization of the predefined calendars found in the - * lib/calendars.properties file. + * Suffix of resource names for Hijrah calendar variants. + */ + private static final String RESOURCE_SUFFIX = ".properties"; + + /** + * Static initialization of the built-in calendars. + * The data is not loaded until it is used. */ static { - try { - calendarProperties = sun.util.calendar.BaseCalendar.getCalendarProperties(); - } catch (IOException ioe) { - throw new InternalError("Can't initialize lib/calendars.properties", ioe); - } - - try { - INSTANCE = new HijrahChronology("Hijrah-umalqura"); - // Register it by its aliases - AbstractChronology.registerChrono(INSTANCE, "Hijrah"); - AbstractChronology.registerChrono(INSTANCE, "islamic"); - } catch (DateTimeException ex) { - // Absence of Hijrah calendar is fatal to initializing this class. - PlatformLogger logger = PlatformLogger.getLogger("java.time.chrono"); - logger.severe("Unable to initialize Hijrah calendar: Hijrah-umalqura", ex); - throw new RuntimeException("Unable to initialize Hijrah-umalqura calendar", ex.getCause()); - } - registerVariants(); + INSTANCE = new HijrahChronology("Hijrah-umalqura", "islamic-umalqura"); + // Register it by its aliases + AbstractChronology.registerChrono(INSTANCE, "Hijrah"); + AbstractChronology.registerChrono(INSTANCE, "islamic"); } /** - * For each Hijrah variant listed, create the HijrahChronology and register it. - * Exceptions during initialization are logged but otherwise ignored. + * Create a HijrahChronology for the named variant and type. + * + * @param id the id of the calendar + * @param calType the typeId of the calendar + * @throws IllegalArgumentException if the id or typeId is empty */ - private static void registerVariants() { - for (String name : calendarProperties.stringPropertyNames()) { - if (name.startsWith(PROP_PREFIX)) { - String id = name.substring(PROP_PREFIX.length()); - if (id.indexOf('.') >= 0) { - continue; // no name or not a simple name of a calendar - } - if (id.equals(INSTANCE.getId())) { - continue; // do not duplicate the default - } - try { - // Create and register the variant - HijrahChronology chrono = new HijrahChronology(id); - AbstractChronology.registerChrono(chrono); - } catch (DateTimeException ex) { - // Log error and continue - PlatformLogger logger = PlatformLogger.getLogger("java.time.chrono"); - logger.severe("Unable to initialize Hijrah calendar: " + id, ex); - } - } - } - } - - /** - * Create a HijrahChronology for the named variant. - * The resource and calendar type are retrieved from properties - * in the {@code calendars.properties}. - * The property names are {@code "calendar.hijrah." + id} - * and {@code "calendar.hijrah." + id + ".type"} - * @param id the id of the calendar - * @throws DateTimeException if the calendar type is missing from the properties file. - * @throws IllegalArgumentException if the id is empty - */ - private HijrahChronology(String id) throws DateTimeException { + private HijrahChronology(String id, String calType) { if (id.isEmpty()) { throw new IllegalArgumentException("calendar id is empty"); } - String propName = PROP_PREFIX + id + PROP_TYPE_SUFFIX; - String calType = calendarProperties.getProperty(propName); - if (calType == null || calType.isEmpty()) { - throw new DateTimeException("calendarType is missing or empty for: " + propName); + if (calType.isEmpty()) { + throw new IllegalArgumentException("calendar typeId is empty"); } this.typeId = id; this.calendarType = calType; @@ -866,30 +796,26 @@ /** * Return the configuration properties from the resource. * <p> - * The default location of the variant configuration resource is: + * The location of the variant configuration resource is: * <pre> - * "$java.home/lib/" + resource-name + * "/java/time/chrono/hijrah-config-" + calendarType + ".properties" * </pre> * - * @param resource the name of the calendar property resource + * @param calendarType the calendarType of the calendar variant * @return a Properties containing the properties read from the resource. * @throws Exception if access to the property resource fails */ - private static Properties readConfigProperties(final String resource) throws Exception { - try { - return AccessController - .doPrivileged((java.security.PrivilegedExceptionAction<Properties>) - () -> { - String libDir = System.getProperty("java.home") + File.separator + "lib"; - File file = new File(libDir, resource); - Properties props = new Properties(); - try (InputStream is = new FileInputStream(file)) { - props.load(is); - } - return props; - }); - } catch (PrivilegedActionException pax) { - throw pax.getException(); + private Properties readConfigProperties(final String calendarType) throws Exception { + String resourceName = RESOURCE_PREFIX + calendarType + RESOURCE_SUFFIX; + PrivilegedAction<InputStream> getResourceAction = () -> HijrahChronology.class.getResourceAsStream(resourceName); + FilePermission perm = new FilePermission("<<ALL FILES>>", "read"); + try (InputStream is = AccessController.doPrivileged(getResourceAction, null, perm)) { + if (is == null) { + throw new RuntimeException("Hijrah calendar resource not found: /java/time/chrono/" + resourceName); + } + Properties props = new Properties(); + props.load(is); + return props; } } @@ -906,9 +832,7 @@ */ private void loadCalendarData() { try { - String resourceName = calendarProperties.getProperty(PROP_PREFIX + typeId); - Objects.requireNonNull(resourceName, "Resource missing for calendar: " + PROP_PREFIX + typeId); - Properties props = readConfigProperties(resourceName); + Properties props = readConfigProperties(calendarType); Map<Integer, int[]> years = new HashMap<>(); int minYear = Integer.MAX_VALUE; @@ -937,7 +861,7 @@ default: try { // Everything else is either a year or invalid - int year = Integer.valueOf(key); + int year = Integer.parseInt(key); int[] months = parseMonths((String) entry.getValue()); years.put(year, months); maxYear = Math.max(maxYear, year); @@ -1045,7 +969,7 @@ } for (int i = 0; i < 12; i++) { try { - months[i] = Integer.valueOf(numbers[i]); + months[i] = Integer.parseInt(numbers[i]); } catch (NumberFormatException nfe) { throw new IllegalArgumentException("bad key: " + numbers[i]); } @@ -1067,9 +991,9 @@ throw new IllegalArgumentException("date must be yyyy-MM-dd"); } int[] ymd = new int[3]; - ymd[0] = Integer.valueOf(string.substring(0, 4)); - ymd[1] = Integer.valueOf(string.substring(5, 7)); - ymd[2] = Integer.valueOf(string.substring(8, 10)); + ymd[0] = Integer.parseInt(string, 0, 4, 10); + ymd[1] = Integer.parseInt(string, 5, 7, 10); + ymd[2] = Integer.parseInt(string, 8, 10, 10); return ymd; } catch (NumberFormatException ex) { throw new IllegalArgumentException("date must be yyyy-MM-dd", ex);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.base/share/classes/java/time/chrono/hijrah-config-islamic-umalqura.properties Wed Jul 05 20:05:54 2017 +0200 @@ -0,0 +1,369 @@ +# Copyright (c) 2013, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# +# This properties file defines a Hijrah calendar variant. +# +# Fields: +# +# <version> ::= 'version' '=' <version string> +# <id> ::= 'id' '=' <id string> +# <type> ::= 'type' '=' <type string> +# <iso-start> ::= 'iso-start' '=' <start date in the ISO calendar> +# <year> ::= <yyyy> '=' <nn nn nn nn nn nn nn nn nn nn nn nn> +# +# version ... (Required) +# +# id ... (Required) +# Identifies the Java Chronology +# +# type ... (Required) +# Identifies the type of calendar in the standard calendar ID scheme +# iso-start ... (Required) +# Specifies the corresponding ISO date to the first Hijrah day +# in the defined range of dates +# +# year ... (Required) +# Number of days for each month of a Hijrah year +# * Each line defines a year. The years must be in chronological +# order and no gap is allowed. +# * Each line is in the form indicated above. <yyyy> is a Hijrah year and +# nn is the number of days for a month listed in the order of the months. +# * Each year must have 12 months. +# * Each month should be 29 or 30 days long. +# * There must be one or more space characters between the months. +# + +# Version of this definition +version=1.8.0_1 + +# Java chronology ID +id=Hijrah-umalqura + +# Standard calendar type specification +type=islamic-umalqura + +# defines the corresponding ISO date to the earliest Hijrah date +iso-start=1882-11-12 + +# 1 2 3 4 5 6 7 8 9 10 11 12 +1300=30 29 30 29 30 29 30 29 30 29 30 29 +1301=30 30 29 30 29 30 29 30 29 30 29 29 +1302=30 30 30 29 30 30 29 29 30 29 29 30 +1303=29 30 30 29 30 30 29 30 29 30 29 29 +1304=29 30 30 29 30 30 30 29 30 29 30 29 +1305=29 29 30 30 29 30 30 29 30 30 29 29 +1306=30 29 30 29 30 29 30 29 30 30 29 30 +1307=29 30 29 30 29 30 29 30 29 30 29 30 +1308=29 30 30 29 30 29 30 29 30 29 29 30 +1309=29 30 30 30 30 29 29 30 29 29 30 29 +1310=30 29 30 30 30 29 30 29 30 29 29 30 +1311=29 30 29 30 30 30 29 30 29 30 29 29 +1312=30 29 30 29 30 30 29 30 30 29 30 29 +1313=29 30 29 30 29 30 29 30 30 30 29 29 +1314=30 30 29 30 29 29 30 29 30 30 29 30 +1315=29 30 30 29 30 29 29 30 29 30 29 30 +1316=29 30 30 30 29 30 29 29 30 29 30 29 +1317=30 29 30 30 29 30 29 30 29 30 29 29 +1318=30 29 30 30 29 30 30 29 30 29 30 29 +1319=29 30 29 30 30 29 30 29 30 30 29 30 +1320=29 30 29 29 30 29 30 29 30 30 30 29 +1321=30 29 30 29 29 30 29 29 30 30 30 30 +1322=29 30 29 30 29 29 29 30 29 30 30 30 +1323=29 30 30 29 30 29 29 29 30 29 30 30 +1324=29 30 30 29 30 29 30 29 29 30 29 30 +1325=30 29 30 29 30 30 29 30 29 30 29 30 +1326=29 29 30 29 30 30 29 30 29 30 30 29 +1327=30 29 29 30 29 30 29 30 30 29 30 30 +1328=29 30 29 29 30 29 29 30 30 30 29 30 +1329=30 29 30 29 29 30 29 29 30 30 29 30 +1330=30 30 29 30 29 29 30 29 29 30 30 29 +1331=30 30 29 30 30 29 29 30 29 30 29 30 +1332=29 30 29 30 30 29 30 29 30 30 29 29 +1333=30 29 29 30 30 29 30 30 29 30 30 29 +1334=29 29 30 29 30 29 30 30 30 29 30 29 +1335=30 29 30 29 29 30 29 30 30 29 30 30 +1336=29 30 29 30 29 29 30 29 30 29 30 30 +1337=30 29 30 29 30 29 29 30 29 30 29 30 +1338=29 30 30 29 30 30 29 29 30 29 30 29 +1339=30 29 30 29 30 30 30 29 30 29 29 30 +1340=29 29 30 29 30 30 30 30 29 30 29 29 +1341=30 29 29 30 29 30 30 30 29 30 30 29 +1342=29 29 30 29 30 29 30 30 29 30 30 29 +1343=30 29 29 30 29 30 29 30 29 30 30 29 +1344=30 29 30 29 30 30 29 29 30 29 30 29 +1345=30 29 30 30 30 29 30 29 29 30 29 29 +1346=30 29 30 30 30 30 29 30 29 29 30 29 +1347=29 30 29 30 30 30 29 30 30 29 29 30 +1348=29 29 30 29 30 30 29 30 30 30 29 29 +1349=30 29 29 30 29 30 30 29 30 30 29 30 +1350=29 30 29 30 29 30 29 29 30 30 29 30 +1351=30 29 30 29 30 29 30 29 29 30 29 30 +1352=30 29 30 30 29 30 29 30 29 29 30 29 +1353=30 29 30 30 30 29 30 29 29 30 29 30 +1354=29 30 29 30 30 29 30 30 29 30 29 29 +1355=30 29 29 30 30 29 30 30 29 30 30 29 +1356=29 30 29 30 29 30 29 30 29 30 30 30 +1357=29 29 30 29 30 29 29 30 29 30 30 30 +1358=29 30 29 30 29 30 29 29 30 29 30 30 +1359=29 30 30 29 30 29 30 29 29 29 30 30 +1360=29 30 30 30 29 30 29 30 29 29 30 29 +1361=30 29 30 30 29 30 30 29 29 30 29 30 +1362=29 30 29 30 29 30 30 29 30 29 30 29 +1363=30 29 30 29 30 29 30 29 30 29 30 30 +1364=29 30 29 30 29 29 30 29 30 29 30 30 +1365=30 30 29 29 30 29 29 30 29 30 29 30 +1366=30 30 29 30 29 30 29 29 30 29 30 29 +1367=30 30 29 30 30 29 30 29 29 30 29 30 +1368=29 30 29 30 30 30 29 29 30 29 30 29 +1369=30 29 30 29 30 30 29 30 29 30 30 29 +1370=30 29 29 30 29 30 29 30 29 30 30 30 +1371=29 30 29 29 30 29 30 29 30 29 30 30 +1372=30 29 29 30 29 30 29 29 30 29 30 30 +1373=30 29 30 29 30 29 30 29 29 30 29 30 +1374=30 29 30 30 29 30 29 30 29 29 30 29 +1375=30 29 30 30 29 30 30 29 30 29 30 29 +1376=29 30 29 30 29 30 30 30 29 30 29 30 +1377=29 29 30 29 29 30 30 30 29 30 30 29 +1378=30 29 29 29 30 29 30 30 29 30 30 30 +1379=29 30 29 29 29 30 29 30 30 29 30 30 +1380=29 30 29 30 29 30 29 30 29 30 29 30 +1381=29 30 29 30 30 29 30 29 30 29 29 30 +1382=29 30 29 30 30 29 30 30 29 30 29 29 +1383=30 29 29 30 30 30 29 30 30 29 30 29 +1384=29 30 29 29 30 30 29 30 30 30 29 30 +1385=29 29 30 29 29 30 30 29 30 30 30 29 +1386=30 29 29 30 29 29 30 30 29 30 30 29 +1387=30 29 30 29 30 29 30 29 30 29 30 29 +1388=30 30 29 30 29 30 29 30 29 30 29 29 +1389=30 30 29 30 30 29 30 30 29 29 30 29 +1390=29 30 29 30 30 30 29 30 29 30 29 30 +1391=29 29 30 29 30 30 29 30 30 29 30 29 +1392=30 29 29 30 29 30 29 30 30 29 30 30 +1393=29 30 29 29 30 29 30 29 30 29 30 30 +1394=30 29 30 29 29 30 29 30 29 30 29 30 +1395=30 29 30 30 29 30 29 29 30 29 29 30 +1396=30 29 30 30 29 30 30 29 29 30 29 29 +1397=30 29 30 30 29 30 30 30 29 29 29 30 +1398=29 30 29 30 30 29 30 30 29 30 29 29 +1399=30 29 30 29 30 29 30 30 29 30 29 30 +1400=30 29 30 29 29 30 29 30 29 30 29 30 +1401=30 30 29 30 29 29 30 29 29 30 29 30 +1402=30 30 30 29 30 29 29 30 29 29 30 29 +1403=30 30 30 29 30 30 29 29 30 29 29 30 +1404=29 30 30 29 30 30 29 30 29 30 29 29 +1405=30 29 30 29 30 30 30 29 30 29 29 30 +1406=30 29 29 30 29 30 30 29 30 29 30 30 +1407=29 30 29 29 30 29 30 29 30 29 30 30 +1408=30 29 30 29 30 29 29 30 29 29 30 30 +1409=30 30 29 30 29 30 29 29 30 29 29 30 +1410=30 30 29 30 30 29 30 29 29 30 29 29 +1411=30 30 29 30 30 29 30 30 29 29 30 29 +1412=30 29 30 29 30 29 30 30 30 29 29 30 +1413=29 30 29 29 30 29 30 30 30 29 30 29 +1414=30 29 30 29 29 30 29 30 30 29 30 30 +1415=29 30 29 30 29 29 30 29 30 29 30 30 +1416=30 29 30 29 30 29 29 30 29 30 29 30 +1417=30 29 30 30 29 29 30 29 30 29 30 29 +1418=30 29 30 30 29 30 29 30 29 30 29 30 +1419=29 30 29 30 29 30 29 30 30 30 29 29 +1420=29 30 29 29 30 29 30 30 30 30 29 30 +1421=29 29 30 29 29 29 30 30 30 30 29 30 +1422=30 29 29 30 29 29 29 30 30 30 29 30 +1423=30 29 30 29 30 29 29 30 29 30 29 30 +1424=30 29 30 30 29 30 29 29 30 29 30 29 +1425=30 29 30 30 29 30 29 30 30 29 30 29 +1426=29 30 29 30 29 30 30 29 30 30 29 30 +1427=29 29 30 29 30 29 30 30 29 30 30 29 +1428=30 29 29 30 29 29 30 30 30 29 30 30 +1429=29 30 29 29 30 29 29 30 30 29 30 30 +1430=29 30 30 29 29 30 29 30 29 30 29 30 +1431=29 30 30 29 30 29 30 29 30 29 29 30 +1432=29 30 30 30 29 30 29 30 29 30 29 29 +1433=30 29 30 30 29 30 30 29 30 29 30 29 +1434=29 30 29 30 29 30 30 29 30 30 29 29 +1435=30 29 30 29 30 29 30 29 30 30 29 30 +1436=29 30 29 30 29 30 29 30 29 30 29 30 +1437=30 29 30 30 29 29 30 29 30 29 29 30 +1438=30 29 30 30 30 29 29 30 29 29 30 29 +1439=30 29 30 30 30 29 30 29 30 29 29 30 +1440=29 30 29 30 30 30 29 30 29 30 29 29 +1441=30 29 30 29 30 30 29 30 30 29 30 29 +1442=29 30 29 30 29 30 29 30 30 29 30 29 +1443=30 29 30 29 30 29 30 29 30 29 30 30 +1444=29 30 29 30 30 29 29 30 29 30 29 30 +1445=29 30 30 30 29 30 29 29 30 29 29 30 +1446=29 30 30 30 29 30 30 29 29 30 29 29 +1447=30 29 30 30 30 29 30 29 30 29 30 29 +1448=29 30 29 30 30 29 30 30 29 30 29 30 +1449=29 29 30 29 30 29 30 30 29 30 30 29 +1450=30 29 30 29 29 30 29 30 29 30 30 29 +1451=30 30 30 29 29 30 29 29 30 30 29 30 +1452=30 29 30 30 29 29 30 29 29 30 29 30 +1453=30 29 30 30 29 30 29 30 29 29 30 29 +1454=30 29 30 30 29 30 30 29 30 29 30 29 +1455=29 30 29 30 30 29 30 29 30 30 29 30 +1456=29 29 30 29 30 29 30 29 30 30 30 29 +1457=30 29 29 30 29 29 30 29 30 30 30 30 +1458=29 30 29 29 30 29 29 30 29 30 30 30 +1459=29 30 30 29 29 30 29 29 30 29 30 30 +1460=29 30 30 29 30 29 30 29 29 30 29 30 +1461=29 30 30 29 30 29 30 29 30 30 29 29 +1462=30 29 30 29 30 30 29 30 29 30 30 29 +1463=29 30 29 30 29 30 29 30 30 30 29 30 +1464=29 30 29 29 30 29 29 30 30 30 29 30 +1465=30 29 30 29 29 30 29 29 30 30 29 30 +1466=30 30 29 30 29 29 29 30 29 30 30 29 +1467=30 30 29 30 30 29 29 30 29 30 29 30 +1468=29 30 29 30 30 29 30 29 30 29 30 29 +1469=29 30 29 30 30 29 30 30 29 30 29 30 +1470=29 29 30 29 30 30 29 30 30 29 30 29 +1471=30 29 29 30 29 30 29 30 30 29 30 30 +1472=29 30 29 29 30 29 30 29 30 30 29 30 +1473=29 30 29 30 30 29 29 30 29 30 29 30 +1474=29 30 30 29 30 30 29 29 30 29 30 29 +1475=29 30 30 29 30 30 30 29 29 30 29 29 +1476=30 29 30 29 30 30 30 29 30 29 30 29 +1477=29 30 29 29 30 30 30 30 29 30 29 30 +1478=29 29 30 29 30 29 30 30 29 30 30 29 +1479=30 29 29 30 29 30 29 30 29 30 30 29 +1480=30 29 30 29 30 29 30 29 30 29 30 29 +1481=30 29 30 30 29 30 29 30 29 30 29 29 +1482=30 29 30 30 30 30 29 30 29 29 30 29 +1483=29 30 29 30 30 30 29 30 30 29 29 30 +1484=29 29 30 29 30 30 30 29 30 29 30 29 +1485=30 29 29 30 29 30 30 29 30 30 29 30 +1486=29 30 29 29 30 29 30 29 30 30 29 30 +1487=30 29 30 29 30 29 29 30 29 30 29 30 +1488=30 29 30 30 29 30 29 29 30 29 30 29 +1489=30 29 30 30 30 29 30 29 29 30 29 30 +1490=29 30 29 30 30 29 30 30 29 29 30 29 +1491=30 29 29 30 30 29 30 30 29 30 29 30 +1492=29 30 29 29 30 30 29 30 29 30 30 29 +1493=30 29 30 29 30 29 29 30 29 30 30 30 +1494=29 30 29 30 29 30 29 29 29 30 30 30 +1495=29 30 30 29 30 29 29 30 29 29 30 30 +1496=29 30 30 30 29 30 29 29 30 29 29 30 +1497=30 29 30 30 29 30 29 30 29 30 29 30 +1498=29 30 29 30 29 30 30 29 30 29 30 29 +1499=30 29 30 29 29 30 30 29 30 29 30 30 +1500=29 30 29 30 29 29 30 29 30 29 30 30 +1501=30 29 30 29 30 29 29 29 30 29 30 30 +1502=30 30 29 30 29 30 29 29 29 30 30 29 +1503=30 30 29 30 30 29 30 29 29 29 30 30 +1504=29 30 29 30 30 30 29 29 30 29 30 29 +1505=30 29 30 29 30 30 29 30 29 30 30 29 +1506=29 30 29 29 30 30 29 30 30 29 30 30 +1507=29 29 30 29 29 30 30 29 30 29 30 30 +1508=30 29 29 30 29 30 29 29 30 29 30 30 +1509=30 29 30 29 30 29 30 29 29 30 29 30 +1510=30 29 30 30 29 30 29 30 29 29 30 29 +1511=30 29 30 30 29 30 30 29 30 29 29 30 +1512=29 30 29 30 29 30 30 30 29 30 29 30 +1513=29 29 29 30 29 30 30 30 29 30 30 29 +1514=30 29 29 29 30 29 30 30 29 30 30 30 +1515=29 29 30 29 29 30 29 30 30 29 30 30 +1516=29 30 29 30 29 29 30 29 30 29 30 30 +1517=29 30 29 30 29 30 30 29 29 30 29 30 +1518=29 30 29 30 30 29 30 30 29 30 29 29 +1519=30 29 29 30 30 30 29 30 30 29 30 29 +1520=29 30 29 29 30 30 30 29 30 30 29 30 +1521=29 29 29 30 29 30 30 29 30 30 29 30 +1522=30 29 29 29 30 29 30 30 29 30 30 29 +1523=30 29 30 29 30 29 30 29 29 30 30 29 +1524=30 30 29 30 29 30 29 30 29 29 30 29 +1525=30 30 29 30 30 29 30 29 30 29 29 30 +1526=29 30 29 30 30 30 29 30 29 30 29 29 +1527=30 29 30 29 30 30 29 30 30 29 30 29 +1528=30 29 29 30 29 30 29 30 30 29 30 30 +1529=29 30 29 29 30 29 30 29 30 29 30 30 +1530=29 30 30 29 29 30 29 30 29 29 30 30 +1531=29 30 30 30 29 29 30 29 30 29 29 30 +1532=29 30 30 30 29 30 30 29 29 29 30 29 +1533=30 29 30 30 30 29 30 29 30 29 29 30 +1534=29 30 29 30 30 29 30 30 29 29 30 29 +1535=30 29 30 29 30 29 30 30 29 30 29 30 +1536=29 30 29 30 29 30 29 30 29 30 29 30 +1537=30 29 30 30 29 29 30 29 29 30 29 30 +1538=30 30 29 30 30 29 29 30 29 29 30 29 +1539=30 30 30 29 30 30 29 29 30 29 29 30 +1540=29 30 30 29 30 30 29 30 29 29 30 29 +1541=30 29 30 29 30 30 30 29 30 29 29 30 +1542=29 30 29 30 29 30 30 29 30 29 30 30 +1543=29 30 29 29 30 29 30 29 30 29 30 30 +1544=30 29 30 29 29 30 29 30 29 30 29 30 +1545=30 30 29 30 29 29 30 29 30 29 29 30 +1546=30 30 29 30 29 30 29 30 29 30 29 29 +1547=30 30 29 30 30 29 30 29 30 29 30 29 +1548=30 29 29 30 30 29 30 30 29 30 29 30 +1549=29 30 29 29 30 29 30 30 30 29 30 29 +1550=30 29 30 29 29 29 30 30 30 29 30 30 +1551=29 30 29 29 30 29 29 30 30 29 30 30 +1552=30 29 30 29 29 30 29 29 30 30 29 30 +1553=30 29 30 29 30 29 30 29 30 29 30 29 +1554=30 29 30 29 30 30 29 30 29 30 29 30 +1555=29 29 30 29 30 30 29 30 30 29 30 29 +1556=30 29 29 30 29 30 29 30 30 30 29 30 +1557=29 30 29 29 29 30 29 30 30 30 30 29 +1558=30 29 30 29 29 29 30 29 30 30 30 29 +1559=30 30 29 29 30 29 29 30 30 29 30 29 +1560=30 30 29 30 29 30 29 30 29 30 29 30 +1561=29 30 30 29 30 29 30 30 29 29 30 29 +1562=29 30 30 29 30 29 30 30 30 29 29 30 +1563=29 30 29 29 30 29 30 30 30 29 30 29 +1564=30 29 30 29 29 30 29 30 30 30 29 30 +1565=29 30 29 30 29 29 30 29 30 30 29 30 +1566=30 29 30 29 30 29 29 30 29 30 29 30 +1567=30 29 30 30 29 30 29 30 29 29 30 29 +1568=30 29 30 30 30 29 30 29 30 29 29 29 +1569=30 29 30 30 30 29 30 30 29 30 29 29 +1570=29 30 29 30 30 29 30 30 30 29 29 30 +1571=29 29 30 29 30 30 29 30 30 29 30 29 +1572=30 29 29 30 29 30 29 30 30 29 30 29 +1573=30 29 30 30 29 30 29 29 30 29 30 29 +1574=30 30 29 30 30 29 30 29 29 30 29 29 +1575=30 30 30 29 30 30 29 30 29 29 29 30 +1576=29 30 30 29 30 30 30 29 30 29 29 29 +1577=30 29 30 30 29 30 30 29 30 29 30 29 +1578=29 30 29 30 29 30 30 29 30 30 29 30 +1579=29 30 29 30 29 29 30 30 29 30 29 30 +1580=29 30 30 29 30 29 29 30 29 30 29 30 +1581=30 30 29 30 29 30 29 29 30 29 30 29 +1582=30 30 29 30 30 29 30 29 30 29 29 29 +1583=30 30 29 30 30 30 29 30 29 30 29 29 +1584=29 30 30 29 30 30 29 30 30 29 30 29 +1585=29 30 29 30 29 30 29 30 30 29 30 30 +1586=29 29 30 29 30 29 29 30 30 30 29 30 +1587=29 30 30 29 29 29 30 29 30 29 30 30 +1588=30 29 30 30 29 29 29 30 29 30 29 30 +1589=30 29 30 30 29 30 29 29 30 29 30 29 +1590=30 29 30 30 30 29 29 30 29 30 29 30 +1591=29 30 29 30 30 29 30 29 30 29 30 29 +1592=30 29 30 29 30 29 30 29 30 30 30 29 +1593=30 29 29 30 29 29 30 29 30 30 30 29 +1594=30 30 29 29 30 29 29 29 30 30 30 30 +1595=29 30 29 30 29 29 30 29 29 30 30 30 +1596=29 30 30 29 30 29 29 30 29 30 29 30 +1597=29 30 30 29 30 29 30 29 30 29 30 29 +1598=30 29 30 29 30 30 29 30 29 30 30 29 +1599=29 30 29 30 29 30 29 30 30 30 29 30 +1600=29 29 30 29 30 29 29 30 30 30 29 30
--- a/jdk/src/java.base/share/classes/java/util/Collection.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/java/util/Collection.java Wed Jul 05 20:05:54 2017 +0200 @@ -518,7 +518,7 @@ * <p>The default implementation should be overridden by subclasses that * can return a more efficient spliterator. In order to * preserve expected laziness behavior for the {@link #stream()} and - * {@link #parallelStream()}} methods, spliterators should either have the + * {@link #parallelStream()} methods, spliterators should either have the * characteristic of {@code IMMUTABLE} or {@code CONCURRENT}, or be * <em><a href="Spliterator.html#binding">late-binding</a></em>. * If none of these is practical, the overriding class should describe the
--- a/jdk/src/java.base/share/classes/java/util/JapaneseImperialCalendar.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/java/util/JapaneseImperialCalendar.java Wed Jul 05 20:05:54 2017 +0200 @@ -97,8 +97,7 @@ * * This implementation uses * sun.util.calendar.LocalGregorianCalendar to perform most of the - * calendar calculations. LocalGregorianCalendar is configurable - * and reads <JRE_HOME>/lib/calendars.properties at the start-up. + * calendar calculations. */ /**
--- a/jdk/src/java.base/share/classes/sun/misc/JavaIOFileDescriptorAccess.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/sun/misc/JavaIOFileDescriptorAccess.java Wed Jul 05 20:05:54 2017 +0200 @@ -33,6 +33,8 @@ public interface JavaIOFileDescriptorAccess { public void set(FileDescriptor obj, int fd); public int get(FileDescriptor fd); + public void setAppend(FileDescriptor obj, boolean append); + public boolean getAppend(FileDescriptor obj); // Only valid on Windows public void setHandle(FileDescriptor obj, long handle);
--- a/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Wed Jul 05 20:05:54 2017 +0200 @@ -44,6 +44,8 @@ import java.util.List; import sun.misc.Cleaner; +import sun.misc.JavaIOFileDescriptorAccess; +import sun.misc.SharedSecrets; import sun.security.action.GetPropertyAction; public class FileChannelImpl @@ -52,6 +54,10 @@ // Memory allocation size for mapping buffers private static final long allocationGranularity; + // Access to FileDispatcher internals + private static final JavaIOFileDescriptorAccess fdAccess = + SharedSecrets.getJavaIOFileDescriptorAccess(); + // Used to make native read and write calls private final FileDispatcher nd; @@ -61,7 +67,6 @@ // File access mode (immutable) private final boolean writable; private final boolean readable; - private final boolean append; // Required to prevent finalization of creating stream (immutable) private final Object parent; @@ -77,31 +82,23 @@ private final Object positionLock = new Object(); private FileChannelImpl(FileDescriptor fd, String path, boolean readable, - boolean writable, boolean append, Object parent) + boolean writable, Object parent) { this.fd = fd; this.readable = readable; this.writable = writable; - this.append = append; this.parent = parent; this.path = path; - this.nd = new FileDispatcherImpl(append); + this.nd = new FileDispatcherImpl(); } - // Used by FileInputStream.getChannel() and RandomAccessFile.getChannel() + // Used by FileInputStream.getChannel(), FileOutputStream.getChannel + // and RandomAccessFile.getChannel() public static FileChannel open(FileDescriptor fd, String path, boolean readable, boolean writable, Object parent) { - return new FileChannelImpl(fd, path, readable, writable, false, parent); - } - - // Used by FileOutputStream.getChannel - public static FileChannel open(FileDescriptor fd, String path, - boolean readable, boolean writable, - boolean append, Object parent) - { - return new FileChannelImpl(fd, path, readable, writable, append, parent); + return new FileChannelImpl(fd, path, readable, writable, parent); } private void ensureOpen() throws IOException { @@ -109,7 +106,6 @@ throw new ClosedChannelException(); } - // -- Standard channel operations -- protected void implCloseChannel() throws IOException { @@ -258,6 +254,7 @@ ti = threads.add(); if (!isOpen()) return 0; + boolean append = fdAccess.getAppend(fd); do { // in append-mode then position is advanced to end before writing p = (append) ? nd.size(fd) : position0(fd, -1); @@ -284,7 +281,7 @@ if (!isOpen()) return null; do { - p = position0(fd, newPosition); + p = position0(fd, newPosition); } while ((p == IOStatus.INTERRUPTED) && isOpen()); return this; } finally {
--- a/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java Wed Jul 05 20:05:54 2017 +0200 @@ -247,7 +247,7 @@ return null; thread = NativeThread.current(); for (;;) { - n = accept0(this.fd, newfd, isaa); + n = accept(this.fd, newfd, isaa); if ((n == IOStatus.INTERRUPTED) && isOpen()) continue; break; @@ -410,6 +410,18 @@ return sb.toString(); } + /** + * Accept a connection on a socket. + * + * @implNote Wrap native call to allow instrumentation. + */ + private int accept(FileDescriptor ssfd, FileDescriptor newfd, + InetSocketAddress[] isaa) + throws IOException + { + return accept0(ssfd, newfd, isaa); + } + // -- Native methods -- // Accepts a new connection, setting the given file descriptor to refer to
--- a/jdk/src/java.base/share/classes/sun/security/ssl/CipherBox.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/sun/security/ssl/CipherBox.java Wed Jul 05 20:05:54 2017 +0200 @@ -560,7 +560,7 @@ + newLen); hd.encodeBuffer( - (ByteBuffer)bb.duplicate().position(pos), System.out); + bb.duplicate().position(pos), System.out); } catch (IOException e) { } } @@ -790,7 +790,7 @@ // The padding data should be filled with the padding length value. int[] results = checkPadding( - (ByteBuffer)bb.duplicate().position(offset + newLen), + bb.duplicate().position(offset + newLen), (byte)(padLen & 0xFF)); if (protocolVersion.v >= ProtocolVersion.TLS10.v) { if (results[0] != 0) { // padding data has invalid bytes
--- a/jdk/src/java.base/share/classes/sun/security/ssl/EngineInputRecord.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/sun/security/ssl/EngineInputRecord.java Wed Jul 05 20:05:54 2017 +0200 @@ -349,8 +349,7 @@ /* * Copy data out of buffer, it's ready to go. */ - ByteBuffer netBB = (ByteBuffer) - (ByteBuffer.allocate(len).put(buf, 0, len).flip()); + ByteBuffer netBB = ByteBuffer.allocate(len).put(buf, 0, len).flip(); engine.writer.putOutboundDataSync(netBB); }
--- a/jdk/src/java.base/share/classes/sun/security/ssl/EngineOutputRecord.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/sun/security/ssl/EngineOutputRecord.java Wed Jul 05 20:05:54 2017 +0200 @@ -113,9 +113,7 @@ /* * Copy data out of buffer, it's ready to go. */ - ByteBuffer netBB = (ByteBuffer) - ByteBuffer.allocate(len).put(buf, off, len).flip(); - + ByteBuffer netBB = ByteBuffer.allocate(len).put(buf, off, len).flip(); writer.putOutboundData(netBB); }
--- a/jdk/src/java.base/share/classes/sun/util/calendar/CalendarSystem.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/sun/util/calendar/CalendarSystem.java Wed Jul 05 20:05:54 2017 +0200 @@ -177,44 +177,6 @@ return (cs == null) ? cal : cs; } - /** - * Returns a {@link Properties} loaded from lib/calendars.properties. - * - * @return a {@link Properties} loaded from lib/calendars.properties - * @throws IOException if an error occurred when reading from the input stream - * @throws IllegalArgumentException if the input stream contains any malformed - * Unicode escape sequences - */ - public static Properties getCalendarProperties() throws IOException { - Properties calendarProps = null; - try { - String homeDir = AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("java.home")); - final String fname = homeDir + File.separator + "lib" + File.separator - + "calendars.properties"; - calendarProps = AccessController.doPrivileged(new PrivilegedExceptionAction<Properties>() { - @Override - public Properties run() throws IOException { - Properties props = new Properties(); - try (FileInputStream fis = new FileInputStream(fname)) { - props.load(fis); - } - return props; - } - }); - } catch (PrivilegedActionException e) { - Throwable cause = e.getCause(); - if (cause instanceof IOException) { - throw (IOException) cause; - } else if (cause instanceof IllegalArgumentException) { - throw (IllegalArgumentException) cause; - } - // Should not happen - throw new InternalError(cause); - } - return calendarProps; - } - //////////////////////////////// Calendar API ////////////////////////////////// /**
--- a/jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNames.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNames.java Wed Jul 05 20:05:54 2017 +0200 @@ -829,7 +829,7 @@ {"Europe/Madrid", CET}, {"Europe/Malta", CET}, {"Europe/Mariehamn", EET}, - {"Europe/Minsk", FET}, + {"Europe/Minsk", MSK}, {"Europe/Monaco", CET}, {"Europe/Moscow", MSK}, {"Europe/Nicosia", EET}, @@ -917,6 +917,9 @@ {"PRT", AST}, {"Pacific/Apia", WST_SAMOA}, {"Pacific/Auckland", NZST}, + {"Pacific/Bougainville", new String[] {"Bougainville Standard Time", "BST", + "Bougainville Daylight Time", "BST", + "Bougainville Time", "BT"}}, {"Pacific/Chatham", CHAST}, {"Pacific/Chuuk", CHUT}, {"Pacific/Easter", EASTER},
--- a/jdk/src/java.base/share/conf/calendars.properties Thu Oct 30 08:34:51 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -# Copyright (c) 2005, 2014, 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. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# 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. -# - -# -# Hijrah calendars -# -calendar.hijrah.Hijrah-umalqura: hijrah-config-umalqura.properties -calendar.hijrah.Hijrah-umalqura.type: islamic-umalqura
--- a/jdk/src/java.base/share/conf/hijrah-config-umalqura.properties Thu Oct 30 08:34:51 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,369 +0,0 @@ -# Copyright (c) 2013, 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. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# 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. -# -# This properties file defines a Hijrah calendar variant. -# -# Fields: -# -# <version> ::= 'version' '=' <version string> -# <id> ::= 'id' '=' <id string> -# <type> ::= 'type' '=' <type string> -# <iso-start> ::= 'iso-start' '=' <start date in the ISO calendar> -# <year> ::= <yyyy> '=' <nn nn nn nn nn nn nn nn nn nn nn nn> -# -# version ... (Required) -# -# id ... (Required) -# Identifies the Java Chronology -# -# type ... (Required) -# Identifies the type of calendar in the standard calendar ID scheme -# iso-start ... (Required) -# Specifies the corresponding ISO date to the first Hijrah day -# in the defined range of dates -# -# year ... (Required) -# Number of days for each month of a Hijrah year -# * Each line defines a year. The years must be in chronological -# order and no gap is allowed. -# * Each line is in the form indicated above. <yyyy> is a Hijrah year and -# nn is the number of days for a month listed in the order of the months. -# * Each year must have 12 months. -# * Each month should be 29 or 30 days long. -# * There must be one or more space characters between the months. -# - -# Version of this definition -version=1.8.0_1 - -# Java chronology ID -id=Hijrah-umalqura - -# Standard calendar type specification -type=islamic-umalqura - -# defines the corresponding ISO date to the earliest Hijrah date -iso-start=1882-11-12 - -# 1 2 3 4 5 6 7 8 9 10 11 12 -1300=30 29 30 29 30 29 30 29 30 29 30 29 -1301=30 30 29 30 29 30 29 30 29 30 29 29 -1302=30 30 30 29 30 30 29 29 30 29 29 30 -1303=29 30 30 29 30 30 29 30 29 30 29 29 -1304=29 30 30 29 30 30 30 29 30 29 30 29 -1305=29 29 30 30 29 30 30 29 30 30 29 29 -1306=30 29 30 29 30 29 30 29 30 30 29 30 -1307=29 30 29 30 29 30 29 30 29 30 29 30 -1308=29 30 30 29 30 29 30 29 30 29 29 30 -1309=29 30 30 30 30 29 29 30 29 29 30 29 -1310=30 29 30 30 30 29 30 29 30 29 29 30 -1311=29 30 29 30 30 30 29 30 29 30 29 29 -1312=30 29 30 29 30 30 29 30 30 29 30 29 -1313=29 30 29 30 29 30 29 30 30 30 29 29 -1314=30 30 29 30 29 29 30 29 30 30 29 30 -1315=29 30 30 29 30 29 29 30 29 30 29 30 -1316=29 30 30 30 29 30 29 29 30 29 30 29 -1317=30 29 30 30 29 30 29 30 29 30 29 29 -1318=30 29 30 30 29 30 30 29 30 29 30 29 -1319=29 30 29 30 30 29 30 29 30 30 29 30 -1320=29 30 29 29 30 29 30 29 30 30 30 29 -1321=30 29 30 29 29 30 29 29 30 30 30 30 -1322=29 30 29 30 29 29 29 30 29 30 30 30 -1323=29 30 30 29 30 29 29 29 30 29 30 30 -1324=29 30 30 29 30 29 30 29 29 30 29 30 -1325=30 29 30 29 30 30 29 30 29 30 29 30 -1326=29 29 30 29 30 30 29 30 29 30 30 29 -1327=30 29 29 30 29 30 29 30 30 29 30 30 -1328=29 30 29 29 30 29 29 30 30 30 29 30 -1329=30 29 30 29 29 30 29 29 30 30 29 30 -1330=30 30 29 30 29 29 30 29 29 30 30 29 -1331=30 30 29 30 30 29 29 30 29 30 29 30 -1332=29 30 29 30 30 29 30 29 30 30 29 29 -1333=30 29 29 30 30 29 30 30 29 30 30 29 -1334=29 29 30 29 30 29 30 30 30 29 30 29 -1335=30 29 30 29 29 30 29 30 30 29 30 30 -1336=29 30 29 30 29 29 30 29 30 29 30 30 -1337=30 29 30 29 30 29 29 30 29 30 29 30 -1338=29 30 30 29 30 30 29 29 30 29 30 29 -1339=30 29 30 29 30 30 30 29 30 29 29 30 -1340=29 29 30 29 30 30 30 30 29 30 29 29 -1341=30 29 29 30 29 30 30 30 29 30 30 29 -1342=29 29 30 29 30 29 30 30 29 30 30 29 -1343=30 29 29 30 29 30 29 30 29 30 30 29 -1344=30 29 30 29 30 30 29 29 30 29 30 29 -1345=30 29 30 30 30 29 30 29 29 30 29 29 -1346=30 29 30 30 30 30 29 30 29 29 30 29 -1347=29 30 29 30 30 30 29 30 30 29 29 30 -1348=29 29 30 29 30 30 29 30 30 30 29 29 -1349=30 29 29 30 29 30 30 29 30 30 29 30 -1350=29 30 29 30 29 30 29 29 30 30 29 30 -1351=30 29 30 29 30 29 30 29 29 30 29 30 -1352=30 29 30 30 29 30 29 30 29 29 30 29 -1353=30 29 30 30 30 29 30 29 29 30 29 30 -1354=29 30 29 30 30 29 30 30 29 30 29 29 -1355=30 29 29 30 30 29 30 30 29 30 30 29 -1356=29 30 29 30 29 30 29 30 29 30 30 30 -1357=29 29 30 29 30 29 29 30 29 30 30 30 -1358=29 30 29 30 29 30 29 29 30 29 30 30 -1359=29 30 30 29 30 29 30 29 29 29 30 30 -1360=29 30 30 30 29 30 29 30 29 29 30 29 -1361=30 29 30 30 29 30 30 29 29 30 29 30 -1362=29 30 29 30 29 30 30 29 30 29 30 29 -1363=30 29 30 29 30 29 30 29 30 29 30 30 -1364=29 30 29 30 29 29 30 29 30 29 30 30 -1365=30 30 29 29 30 29 29 30 29 30 29 30 -1366=30 30 29 30 29 30 29 29 30 29 30 29 -1367=30 30 29 30 30 29 30 29 29 30 29 30 -1368=29 30 29 30 30 30 29 29 30 29 30 29 -1369=30 29 30 29 30 30 29 30 29 30 30 29 -1370=30 29 29 30 29 30 29 30 29 30 30 30 -1371=29 30 29 29 30 29 30 29 30 29 30 30 -1372=30 29 29 30 29 30 29 29 30 29 30 30 -1373=30 29 30 29 30 29 30 29 29 30 29 30 -1374=30 29 30 30 29 30 29 30 29 29 30 29 -1375=30 29 30 30 29 30 30 29 30 29 30 29 -1376=29 30 29 30 29 30 30 30 29 30 29 30 -1377=29 29 30 29 29 30 30 30 29 30 30 29 -1378=30 29 29 29 30 29 30 30 29 30 30 30 -1379=29 30 29 29 29 30 29 30 30 29 30 30 -1380=29 30 29 30 29 30 29 30 29 30 29 30 -1381=29 30 29 30 30 29 30 29 30 29 29 30 -1382=29 30 29 30 30 29 30 30 29 30 29 29 -1383=30 29 29 30 30 30 29 30 30 29 30 29 -1384=29 30 29 29 30 30 29 30 30 30 29 30 -1385=29 29 30 29 29 30 30 29 30 30 30 29 -1386=30 29 29 30 29 29 30 30 29 30 30 29 -1387=30 29 30 29 30 29 30 29 30 29 30 29 -1388=30 30 29 30 29 30 29 30 29 30 29 29 -1389=30 30 29 30 30 29 30 30 29 29 30 29 -1390=29 30 29 30 30 30 29 30 29 30 29 30 -1391=29 29 30 29 30 30 29 30 30 29 30 29 -1392=30 29 29 30 29 30 29 30 30 29 30 30 -1393=29 30 29 29 30 29 30 29 30 29 30 30 -1394=30 29 30 29 29 30 29 30 29 30 29 30 -1395=30 29 30 30 29 30 29 29 30 29 29 30 -1396=30 29 30 30 29 30 30 29 29 30 29 29 -1397=30 29 30 30 29 30 30 30 29 29 29 30 -1398=29 30 29 30 30 29 30 30 29 30 29 29 -1399=30 29 30 29 30 29 30 30 29 30 29 30 -1400=30 29 30 29 29 30 29 30 29 30 29 30 -1401=30 30 29 30 29 29 30 29 29 30 29 30 -1402=30 30 30 29 30 29 29 30 29 29 30 29 -1403=30 30 30 29 30 30 29 29 30 29 29 30 -1404=29 30 30 29 30 30 29 30 29 30 29 29 -1405=30 29 30 29 30 30 30 29 30 29 29 30 -1406=30 29 29 30 29 30 30 29 30 29 30 30 -1407=29 30 29 29 30 29 30 29 30 29 30 30 -1408=30 29 30 29 30 29 29 30 29 29 30 30 -1409=30 30 29 30 29 30 29 29 30 29 29 30 -1410=30 30 29 30 30 29 30 29 29 30 29 29 -1411=30 30 29 30 30 29 30 30 29 29 30 29 -1412=30 29 30 29 30 29 30 30 30 29 29 30 -1413=29 30 29 29 30 29 30 30 30 29 30 29 -1414=30 29 30 29 29 30 29 30 30 29 30 30 -1415=29 30 29 30 29 29 30 29 30 29 30 30 -1416=30 29 30 29 30 29 29 30 29 30 29 30 -1417=30 29 30 30 29 29 30 29 30 29 30 29 -1418=30 29 30 30 29 30 29 30 29 30 29 30 -1419=29 30 29 30 29 30 29 30 30 30 29 29 -1420=29 30 29 29 30 29 30 30 30 30 29 30 -1421=29 29 30 29 29 29 30 30 30 30 29 30 -1422=30 29 29 30 29 29 29 30 30 30 29 30 -1423=30 29 30 29 30 29 29 30 29 30 29 30 -1424=30 29 30 30 29 30 29 29 30 29 30 29 -1425=30 29 30 30 29 30 29 30 30 29 30 29 -1426=29 30 29 30 29 30 30 29 30 30 29 30 -1427=29 29 30 29 30 29 30 30 29 30 30 29 -1428=30 29 29 30 29 29 30 30 30 29 30 30 -1429=29 30 29 29 30 29 29 30 30 29 30 30 -1430=29 30 30 29 29 30 29 30 29 30 29 30 -1431=29 30 30 29 30 29 30 29 30 29 29 30 -1432=29 30 30 30 29 30 29 30 29 30 29 29 -1433=30 29 30 30 29 30 30 29 30 29 30 29 -1434=29 30 29 30 29 30 30 29 30 30 29 29 -1435=30 29 30 29 30 29 30 29 30 30 29 30 -1436=29 30 29 30 29 30 29 30 29 30 29 30 -1437=30 29 30 30 29 29 30 29 30 29 29 30 -1438=30 29 30 30 30 29 29 30 29 29 30 29 -1439=30 29 30 30 30 29 30 29 30 29 29 30 -1440=29 30 29 30 30 30 29 30 29 30 29 29 -1441=30 29 30 29 30 30 29 30 30 29 30 29 -1442=29 30 29 30 29 30 29 30 30 29 30 29 -1443=30 29 30 29 30 29 30 29 30 29 30 30 -1444=29 30 29 30 30 29 29 30 29 30 29 30 -1445=29 30 30 30 29 30 29 29 30 29 29 30 -1446=29 30 30 30 29 30 30 29 29 30 29 29 -1447=30 29 30 30 30 29 30 29 30 29 30 29 -1448=29 30 29 30 30 29 30 30 29 30 29 30 -1449=29 29 30 29 30 29 30 30 29 30 30 29 -1450=30 29 30 29 29 30 29 30 29 30 30 29 -1451=30 30 30 29 29 30 29 29 30 30 29 30 -1452=30 29 30 30 29 29 30 29 29 30 29 30 -1453=30 29 30 30 29 30 29 30 29 29 30 29 -1454=30 29 30 30 29 30 30 29 30 29 30 29 -1455=29 30 29 30 30 29 30 29 30 30 29 30 -1456=29 29 30 29 30 29 30 29 30 30 30 29 -1457=30 29 29 30 29 29 30 29 30 30 30 30 -1458=29 30 29 29 30 29 29 30 29 30 30 30 -1459=29 30 30 29 29 30 29 29 30 29 30 30 -1460=29 30 30 29 30 29 30 29 29 30 29 30 -1461=29 30 30 29 30 29 30 29 30 30 29 29 -1462=30 29 30 29 30 30 29 30 29 30 30 29 -1463=29 30 29 30 29 30 29 30 30 30 29 30 -1464=29 30 29 29 30 29 29 30 30 30 29 30 -1465=30 29 30 29 29 30 29 29 30 30 29 30 -1466=30 30 29 30 29 29 29 30 29 30 30 29 -1467=30 30 29 30 30 29 29 30 29 30 29 30 -1468=29 30 29 30 30 29 30 29 30 29 30 29 -1469=29 30 29 30 30 29 30 30 29 30 29 30 -1470=29 29 30 29 30 30 29 30 30 29 30 29 -1471=30 29 29 30 29 30 29 30 30 29 30 30 -1472=29 30 29 29 30 29 30 29 30 30 29 30 -1473=29 30 29 30 30 29 29 30 29 30 29 30 -1474=29 30 30 29 30 30 29 29 30 29 30 29 -1475=29 30 30 29 30 30 30 29 29 30 29 29 -1476=30 29 30 29 30 30 30 29 30 29 30 29 -1477=29 30 29 29 30 30 30 30 29 30 29 30 -1478=29 29 30 29 30 29 30 30 29 30 30 29 -1479=30 29 29 30 29 30 29 30 29 30 30 29 -1480=30 29 30 29 30 29 30 29 30 29 30 29 -1481=30 29 30 30 29 30 29 30 29 30 29 29 -1482=30 29 30 30 30 30 29 30 29 29 30 29 -1483=29 30 29 30 30 30 29 30 30 29 29 30 -1484=29 29 30 29 30 30 30 29 30 29 30 29 -1485=30 29 29 30 29 30 30 29 30 30 29 30 -1486=29 30 29 29 30 29 30 29 30 30 29 30 -1487=30 29 30 29 30 29 29 30 29 30 29 30 -1488=30 29 30 30 29 30 29 29 30 29 30 29 -1489=30 29 30 30 30 29 30 29 29 30 29 30 -1490=29 30 29 30 30 29 30 30 29 29 30 29 -1491=30 29 29 30 30 29 30 30 29 30 29 30 -1492=29 30 29 29 30 30 29 30 29 30 30 29 -1493=30 29 30 29 30 29 29 30 29 30 30 30 -1494=29 30 29 30 29 30 29 29 29 30 30 30 -1495=29 30 30 29 30 29 29 30 29 29 30 30 -1496=29 30 30 30 29 30 29 29 30 29 29 30 -1497=30 29 30 30 29 30 29 30 29 30 29 30 -1498=29 30 29 30 29 30 30 29 30 29 30 29 -1499=30 29 30 29 29 30 30 29 30 29 30 30 -1500=29 30 29 30 29 29 30 29 30 29 30 30 -1501=30 29 30 29 30 29 29 29 30 29 30 30 -1502=30 30 29 30 29 30 29 29 29 30 30 29 -1503=30 30 29 30 30 29 30 29 29 29 30 30 -1504=29 30 29 30 30 30 29 29 30 29 30 29 -1505=30 29 30 29 30 30 29 30 29 30 30 29 -1506=29 30 29 29 30 30 29 30 30 29 30 30 -1507=29 29 30 29 29 30 30 29 30 29 30 30 -1508=30 29 29 30 29 30 29 29 30 29 30 30 -1509=30 29 30 29 30 29 30 29 29 30 29 30 -1510=30 29 30 30 29 30 29 30 29 29 30 29 -1511=30 29 30 30 29 30 30 29 30 29 29 30 -1512=29 30 29 30 29 30 30 30 29 30 29 30 -1513=29 29 29 30 29 30 30 30 29 30 30 29 -1514=30 29 29 29 30 29 30 30 29 30 30 30 -1515=29 29 30 29 29 30 29 30 30 29 30 30 -1516=29 30 29 30 29 29 30 29 30 29 30 30 -1517=29 30 29 30 29 30 30 29 29 30 29 30 -1518=29 30 29 30 30 29 30 30 29 30 29 29 -1519=30 29 29 30 30 30 29 30 30 29 30 29 -1520=29 30 29 29 30 30 30 29 30 30 29 30 -1521=29 29 29 30 29 30 30 29 30 30 29 30 -1522=30 29 29 29 30 29 30 30 29 30 30 29 -1523=30 29 30 29 30 29 30 29 29 30 30 29 -1524=30 30 29 30 29 30 29 30 29 29 30 29 -1525=30 30 29 30 30 29 30 29 30 29 29 30 -1526=29 30 29 30 30 30 29 30 29 30 29 29 -1527=30 29 30 29 30 30 29 30 30 29 30 29 -1528=30 29 29 30 29 30 29 30 30 29 30 30 -1529=29 30 29 29 30 29 30 29 30 29 30 30 -1530=29 30 30 29 29 30 29 30 29 29 30 30 -1531=29 30 30 30 29 29 30 29 30 29 29 30 -1532=29 30 30 30 29 30 30 29 29 29 30 29 -1533=30 29 30 30 30 29 30 29 30 29 29 30 -1534=29 30 29 30 30 29 30 30 29 29 30 29 -1535=30 29 30 29 30 29 30 30 29 30 29 30 -1536=29 30 29 30 29 30 29 30 29 30 29 30 -1537=30 29 30 30 29 29 30 29 29 30 29 30 -1538=30 30 29 30 30 29 29 30 29 29 30 29 -1539=30 30 30 29 30 30 29 29 30 29 29 30 -1540=29 30 30 29 30 30 29 30 29 29 30 29 -1541=30 29 30 29 30 30 30 29 30 29 29 30 -1542=29 30 29 30 29 30 30 29 30 29 30 30 -1543=29 30 29 29 30 29 30 29 30 29 30 30 -1544=30 29 30 29 29 30 29 30 29 30 29 30 -1545=30 30 29 30 29 29 30 29 30 29 29 30 -1546=30 30 29 30 29 30 29 30 29 30 29 29 -1547=30 30 29 30 30 29 30 29 30 29 30 29 -1548=30 29 29 30 30 29 30 30 29 30 29 30 -1549=29 30 29 29 30 29 30 30 30 29 30 29 -1550=30 29 30 29 29 29 30 30 30 29 30 30 -1551=29 30 29 29 30 29 29 30 30 29 30 30 -1552=30 29 30 29 29 30 29 29 30 30 29 30 -1553=30 29 30 29 30 29 30 29 30 29 30 29 -1554=30 29 30 29 30 30 29 30 29 30 29 30 -1555=29 29 30 29 30 30 29 30 30 29 30 29 -1556=30 29 29 30 29 30 29 30 30 30 29 30 -1557=29 30 29 29 29 30 29 30 30 30 30 29 -1558=30 29 30 29 29 29 30 29 30 30 30 29 -1559=30 30 29 29 30 29 29 30 30 29 30 29 -1560=30 30 29 30 29 30 29 30 29 30 29 30 -1561=29 30 30 29 30 29 30 30 29 29 30 29 -1562=29 30 30 29 30 29 30 30 30 29 29 30 -1563=29 30 29 29 30 29 30 30 30 29 30 29 -1564=30 29 30 29 29 30 29 30 30 30 29 30 -1565=29 30 29 30 29 29 30 29 30 30 29 30 -1566=30 29 30 29 30 29 29 30 29 30 29 30 -1567=30 29 30 30 29 30 29 30 29 29 30 29 -1568=30 29 30 30 30 29 30 29 30 29 29 29 -1569=30 29 30 30 30 29 30 30 29 30 29 29 -1570=29 30 29 30 30 29 30 30 30 29 29 30 -1571=29 29 30 29 30 30 29 30 30 29 30 29 -1572=30 29 29 30 29 30 29 30 30 29 30 29 -1573=30 29 30 30 29 30 29 29 30 29 30 29 -1574=30 30 29 30 30 29 30 29 29 30 29 29 -1575=30 30 30 29 30 30 29 30 29 29 29 30 -1576=29 30 30 29 30 30 30 29 30 29 29 29 -1577=30 29 30 30 29 30 30 29 30 29 30 29 -1578=29 30 29 30 29 30 30 29 30 30 29 30 -1579=29 30 29 30 29 29 30 30 29 30 29 30 -1580=29 30 30 29 30 29 29 30 29 30 29 30 -1581=30 30 29 30 29 30 29 29 30 29 30 29 -1582=30 30 29 30 30 29 30 29 30 29 29 29 -1583=30 30 29 30 30 30 29 30 29 30 29 29 -1584=29 30 30 29 30 30 29 30 30 29 30 29 -1585=29 30 29 30 29 30 29 30 30 29 30 30 -1586=29 29 30 29 30 29 29 30 30 30 29 30 -1587=29 30 30 29 29 29 30 29 30 29 30 30 -1588=30 29 30 30 29 29 29 30 29 30 29 30 -1589=30 29 30 30 29 30 29 29 30 29 30 29 -1590=30 29 30 30 30 29 29 30 29 30 29 30 -1591=29 30 29 30 30 29 30 29 30 29 30 29 -1592=30 29 30 29 30 29 30 29 30 30 30 29 -1593=30 29 29 30 29 29 30 29 30 30 30 29 -1594=30 30 29 29 30 29 29 29 30 30 30 30 -1595=29 30 29 30 29 29 30 29 29 30 30 30 -1596=29 30 30 29 30 29 29 30 29 30 29 30 -1597=29 30 30 29 30 29 30 29 30 29 30 29 -1598=30 29 30 29 30 30 29 30 29 30 30 29 -1599=29 30 29 30 29 30 29 30 30 30 29 30 -1600=29 29 30 29 30 29 29 30 30 30 29 30
--- a/jdk/src/java.base/share/native/libjava/io_util.h Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/share/native/libjava/io_util.h Wed Jul 05 20:05:54 2017 +0200 @@ -28,6 +28,7 @@ extern jfieldID IO_fd_fdID; extern jfieldID IO_handle_fdID; +extern jfieldID IO_append_fdID; #ifdef _ALLBSD_SOURCE #include <fcntl.h>
--- a/jdk/src/java.base/unix/classes/java/io/FileDescriptor.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/unix/classes/java/io/FileDescriptor.java Wed Jul 05 20:05:54 2017 +0200 @@ -52,15 +52,21 @@ private boolean closed; /** + * true, if file is opened for appending. + */ + private boolean append; + + /** * Constructs an (invalid) FileDescriptor * object. */ - public /**/ FileDescriptor() { + public FileDescriptor() { fd = -1; } - private /* */ FileDescriptor(int fd) { + private FileDescriptor(int fd) { this.fd = fd; + this.append = getAppend(fd); } /** @@ -149,6 +155,14 @@ return obj.fd; } + public void setAppend(FileDescriptor obj, boolean append) { + obj.append = append; + } + + public boolean getAppend(FileDescriptor obj) { + return obj.append; + } + public void setHandle(FileDescriptor obj, long handle) { throw new UnsupportedOperationException(); } @@ -160,6 +174,11 @@ ); } + /** + * Returns true, if the file was opened for appending. + */ + private static native boolean getAppend(int fd); + /* * Package private methods to track referents. * If multiple streams point to the same FileDescriptor, we cycle
--- a/jdk/src/java.base/unix/classes/sun/nio/ch/FileDispatcherImpl.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/unix/classes/sun/nio/ch/FileDispatcherImpl.java Wed Jul 05 20:05:54 2017 +0200 @@ -35,10 +35,6 @@ init(); } - FileDispatcherImpl(boolean append) { - /* append is ignored */ - } - FileDispatcherImpl() { }
--- a/jdk/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java Wed Jul 05 20:05:54 2017 +0200 @@ -141,7 +141,7 @@ Throwable exc = null; try { begin(); - int n = accept0(this.fd, newfd, isaa); + int n = accept(this.fd, newfd, isaa); // spurious wakeup, is this possible? if (n == IOStatus.UNAVAILABLE) { @@ -277,7 +277,7 @@ try { begin(); - int n = accept0(this.fd, newfd, isaa); + int n = accept(this.fd, newfd, isaa); if (n == IOStatus.UNAVAILABLE) { // need calling context when there is security manager as @@ -332,6 +332,18 @@ } } + /** + * Accept a connection on a socket. + * + * @implNote Wrap native call to allow instrumentation. + */ + private int accept(FileDescriptor ssfd, FileDescriptor newfd, + InetSocketAddress[] isaa) + throws IOException + { + return accept0(ssfd, newfd, isaa); + } + // -- Native methods -- private static native void initIDs();
--- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixChannelFactory.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixChannelFactory.java Wed Jul 05 20:05:54 2017 +0200 @@ -134,7 +134,7 @@ throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed"); FileDescriptor fdObj = open(dfd, path, pathForPermissionCheck, flags, mode); - return FileChannelImpl.open(fdObj, path.toString(), flags.read, flags.write, flags.append, null); + return FileChannelImpl.open(fdObj, path.toString(), flags.read, flags.write, null); } /** @@ -288,6 +288,7 @@ // create java.io.FileDescriptor FileDescriptor fdObj = new FileDescriptor(); fdAccess.set(fdObj, fd); + fdAccess.setAppend(fdObj, flags.append); return fdObj; } }
--- a/jdk/src/java.base/unix/native/libjava/FileDescriptor_md.c Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/unix/native/libjava/FileDescriptor_md.c Wed Jul 05 20:05:54 2017 +0200 @@ -23,6 +23,9 @@ * questions. */ +#include <unistd.h> +#include <fcntl.h> + #include "jvm.h" #include "io_util_md.h" @@ -35,6 +38,9 @@ /* field id for jint 'fd' in java.io.FileDescriptor */ jfieldID IO_fd_fdID; +/* field id for jboolean 'append' in java.io.FileDescriptor */ +jfieldID IO_append_fdID; + /************************************************************** * static methods to store field ID's in initializers */ @@ -42,6 +48,7 @@ JNIEXPORT void JNICALL Java_java_io_FileDescriptor_initIDs(JNIEnv *env, jclass fdClass) { IO_fd_fdID = (*env)->GetFieldID(env, fdClass, "fd", "I"); + IO_append_fdID = (*env)->GetFieldID(env, fdClass, "append", "Z"); } /************************************************************** @@ -55,3 +62,9 @@ JNU_ThrowByName(env, "java/io/SyncFailedException", "sync failed"); } } + +JNIEXPORT jboolean JNICALL +Java_java_io_FileDescriptor_getAppend(JNIEnv *env, jclass fdClass, jint fd) { + int flags = fcntl(fd, F_GETFL); + return ((flags & O_APPEND) == 0) ? JNI_FALSE : JNI_TRUE; +}
--- a/jdk/src/java.base/unix/native/libjava/io_util_md.c Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/unix/native/libjava/io_util_md.c Wed Jul 05 20:05:54 2017 +0200 @@ -107,7 +107,15 @@ #endif fd = handleOpen(ps, flags, 0666); if (fd != -1) { + jobject fdobj; + jboolean append; SET_FD(this, fd, fid); + + fdobj = (*env)->GetObjectField(env, this, fid); + if (fdobj != NULL) { + append = (flags & O_APPEND) == 0 ? JNI_FALSE : JNI_TRUE; + (*env)->SetBooleanField(env, fdobj, IO_append_fdID, append); + } } else { throwFileNotFoundException(env, path); }
--- a/jdk/src/java.base/windows/classes/java/io/FileDescriptor.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/windows/classes/java/io/FileDescriptor.java Wed Jul 05 20:05:54 2017 +0200 @@ -51,6 +51,11 @@ private boolean closed; /** + * true, if file is opened for appending. + */ + private boolean append; + + /** * Constructs an (invalid) FileDescriptor * object. */ @@ -75,6 +80,14 @@ return obj.fd; } + public void setAppend(FileDescriptor obj, boolean append) { + obj.append = append; + } + + public boolean getAppend(FileDescriptor obj) { + return obj.append; + } + public void setHandle(FileDescriptor obj, long handle) { obj.handle = handle; }
--- a/jdk/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java Wed Jul 05 20:05:54 2017 +0200 @@ -31,22 +31,14 @@ class FileDispatcherImpl extends FileDispatcher { + private static final JavaIOFileDescriptorAccess fdAccess = + SharedSecrets.getJavaIOFileDescriptorAccess(); + static { IOUtil.load(); } - /** - * Indicates if the dispatcher should first advance the file position - * to the end of file when writing. - */ - private final boolean append; - - FileDispatcherImpl(boolean append) { - this.append = append; - } - FileDispatcherImpl() { - this(false); } @Override @@ -71,7 +63,7 @@ } int write(FileDescriptor fd, long address, int len) throws IOException { - return write0(fd, address, len, append); + return write0(fd, address, len, fdAccess.getAppend(fd)); } int pwrite(FileDescriptor fd, long address, int len, long position) @@ -81,7 +73,7 @@ } long writev(FileDescriptor fd, long address, int len) throws IOException { - return writev0(fd, address, len, append); + return writev0(fd, address, len, fdAccess.getAppend(fd)); } int force(FileDescriptor fd, boolean metaData) throws IOException { @@ -112,8 +104,6 @@ FileDescriptor duplicateForMapping(FileDescriptor fd) throws IOException { // on Windows we need to keep a handle to the file - JavaIOFileDescriptorAccess fdAccess = - SharedSecrets.getJavaIOFileDescriptorAccess(); FileDescriptor result = new FileDescriptor(); long handle = duplicateHandle(fdAccess.getHandle(fd)); fdAccess.setHandle(result, handle);
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsChannelFactory.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsChannelFactory.java Wed Jul 05 20:05:54 2017 +0200 @@ -160,7 +160,7 @@ throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed"); FileDescriptor fdObj = open(pathForWindows, pathToCheck, flags, pSecurityDescriptor); - return FileChannelImpl.open(fdObj, pathForWindows, flags.read, flags.write, flags.append, null); + return FileChannelImpl.open(fdObj, pathForWindows, flags.read, flags.write, null); } /** @@ -339,6 +339,7 @@ // create FileDescriptor and return FileDescriptor fdObj = new FileDescriptor(); fdAccess.setHandle(fdObj, handle); + fdAccess.setAppend(fdObj, flags.append); return fdObj; } }
--- a/jdk/src/java.base/windows/native/libjava/FileDescriptor_md.c Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/windows/native/libjava/FileDescriptor_md.c Wed Jul 05 20:05:54 2017 +0200 @@ -42,6 +42,9 @@ /* field id for jlong 'handle' in java.io.FileDescriptor */ jfieldID IO_handle_fdID; +/* field id for jboolean 'append' in java.io.FileDescriptor */ +jfieldID IO_append_fdID; + /************************************************************** * static methods to store field IDs in initializers */ @@ -50,6 +53,7 @@ Java_java_io_FileDescriptor_initIDs(JNIEnv *env, jclass fdClass) { CHECK_NULL(IO_fd_fdID = (*env)->GetFieldID(env, fdClass, "fd", "I")); CHECK_NULL(IO_handle_fdID = (*env)->GetFieldID(env, fdClass, "handle", "J")); + CHECK_NULL(IO_append_fdID = (*env)->GetFieldID(env, fdClass, "append", "Z")); } JNIEXPORT jlong JNICALL
--- a/jdk/src/java.base/windows/native/libjava/io_util_md.c Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.base/windows/native/libjava/io_util_md.c Wed Jul 05 20:05:54 2017 +0200 @@ -275,7 +275,15 @@ { FD h = winFileHandleOpen(env, path, flags); if (h >= 0) { + jobject fdobj; + jboolean append; SET_FD(this, h, fid); + + fdobj = (*env)->GetObjectField(env, this, fid); + if (fdobj != NULL) { + append = (flags & O_APPEND) == 0 ? JNI_FALSE : JNI_TRUE; + (*env)->SetBooleanField(env, fdobj, IO_append_fdID, append); + } } }
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaIcon.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaIcon.java Wed Jul 05 20:05:54 2017 +0200 @@ -62,7 +62,7 @@ if (w <= 0 || h <= 0) return null; // This could be any kind of icon, so we need to make a buffer for it, draw it and then pass the new image off to appkit. - final BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + final BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE); final Graphics g = image.getGraphics(); i.paintIcon(null, g, 0, 0); g.dispose();
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaImageFactory.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaImageFactory.java Wed Jul 05 20:05:54 2017 +0200 @@ -129,7 +129,7 @@ }; final BufferedImage image = new BufferedImage(scaledAlertIconSize, - scaledAlertIconSize, BufferedImage.TYPE_INT_ARGB); + scaledAlertIconSize, BufferedImage.TYPE_INT_ARGB_PRE); final Graphics g = image.getGraphics(); g.drawImage(background, 0, 0, scaledAlertIconSize, scaledAlertIconSize, null);
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaNativeResources.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaNativeResources.java Wed Jul 05 20:05:54 2017 +0200 @@ -67,11 +67,12 @@ } static BufferedImage getRadioButtonSizerImage() { - final BufferedImage img = new BufferedImage(20, 20, BufferedImage.TYPE_INT_ARGB); + final BufferedImage img = new BufferedImage(20, 20, BufferedImage.TYPE_INT_ARGB_PRE); Graphics g = img.getGraphics(); g.setColor(Color.pink); g.fillRect(0, 0, 20, 20); + g.dispose(); return img; }
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed Jul 05 20:05:54 2017 +0200 @@ -676,6 +676,13 @@ @Override // PlatformWindow public void toFront() { final long nsWindowPtr = getNSWindowPtr(); + LWCToolkit lwcToolkit = (LWCToolkit) Toolkit.getDefaultToolkit(); + Window w = DefaultKeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); + if( w != null + && ((LWWindowPeer)w.getPeer()).getPeerType() == LWWindowPeer.PeerType.EMBEDDED_FRAME + && !lwcToolkit.isApplicationActive()) { + lwcToolkit.activateApplicationIgnoringOtherApps(); + } updateFocusabilityForAutoRequestFocus(false); nativePushNSWindowToFront(nsWindowPtr); updateFocusabilityForAutoRequestFocus(true);
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Wed Jul 05 20:05:54 2017 +0200 @@ -811,6 +811,11 @@ */ public static native boolean isEmbedded(); + /* + * Activates application ignoring other apps. + */ + public native void activateApplicationIgnoringOtherApps(); + /************************ * Native methods section ************************/
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m Wed Jul 05 20:05:54 2017 +0200 @@ -606,6 +606,23 @@ return active; } +/* + * Class: sun_lwawt_macosx_LWCToolkit + * Method: activateApplicationIgnoringOtherApps + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_activateApplicationIgnoringOtherApps +(JNIEnv *env, jclass clazz) +{ + JNF_COCOA_ENTER(env); + [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ + if(![NSApp isActive]){ + [NSApp activateIgnoringOtherApps:YES]; + } + }]; + JNF_COCOA_EXIT(env); +} + /* * Class: sun_awt_SunToolkit
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.desktop/share/classes/META-INF/services/javax.print.PrintServiceLookup Wed Jul 05 20:05:54 2017 +0200 @@ -0,0 +1,2 @@ +# Provider for Java Print Service +sun.print.PrintServiceLookupProvider
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.desktop/share/classes/META-INF/services/javax.print.StreamPrintServiceFactory Wed Jul 05 20:05:54 2017 +0200 @@ -0,0 +1,2 @@ +# Provider for Java 2D Stream print services. +sun.print.PSStreamPrinterFactory
--- a/jdk/src/java.desktop/share/classes/java/awt/Container.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/share/classes/java/awt/Container.java Wed Jul 05 20:05:54 2017 +0200 @@ -3696,7 +3696,7 @@ private void writeObject(ObjectOutputStream s) throws IOException { ObjectOutputStream.PutField f = s.putFields(); f.put("ncomponents", component.size()); - f.put("component", getComponentsSync()); + f.put("component", component.toArray(EMPTY_ARRAY)); f.put("layoutMgr", layoutMgr); f.put("dispatcher", dispatcher); f.put("maxSize", maxSize);
--- a/jdk/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java Wed Jul 05 20:05:54 2017 +0200 @@ -48,6 +48,7 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.FilePermission; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; @@ -1857,7 +1858,13 @@ * returns null. */ private static InputStream getStandardProfileInputStream(String fileName) { - return PCMM.class.getResourceAsStream("profiles/" + fileName); + return AccessController.doPrivileged( + new PrivilegedAction<InputStream>() { + public InputStream run () { + return + PCMM.class.getResourceAsStream("profiles/" + fileName); + } + }, null, new FilePermission("<<ALL FILES>>", "read")); } /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/BorderFactory.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/share/classes/javax/swing/BorderFactory.java Wed Jul 05 20:05:54 2017 +0200 @@ -35,7 +35,7 @@ * possible, this factory will hand out references to shared * <code>Border</code> instances. * For further information and examples see - * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/border.htmll">How + * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/border.html">How to Use Borders</a>, * a section in <em>The Java Tutorial</em>. *
--- a/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java Wed Jul 05 20:05:54 2017 +0200 @@ -126,7 +126,7 @@ * that includes double buffering and support for borders. * For more information see <a * href="http://www.oracle.com/technetwork/java/painting-140037.html#swing">Painting</a> and - * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/border.htmll">How + * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/border.html">How * to Use Borders</a>, * both of which are sections in <em>The Java Tutorial</em>. * </ul>
--- a/jdk/src/java.desktop/share/classes/javax/swing/JInternalFrame.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/share/classes/javax/swing/JInternalFrame.java Wed Jul 05 20:05:54 2017 +0200 @@ -1141,14 +1141,15 @@ /** * Sets an image to be displayed in the titlebar of this internal frame (usually * in the top-left corner). + * Some look and feels might not support displaying an icon in the titlebar. + * * This image is not the <code>desktopIcon</code> object, which * is the image displayed in the <code>JDesktop</code> when * this internal frame is iconified. * * Passing <code>null</code> to this function is valid, - * but the look and feel - * can choose the - * appropriate behavior for that situation, such as displaying no icon + * but the look and feel can choose the appropriate behavior + * for that situation, such as displaying no icon * or a default icon for the look and feel. * * @param icon the <code>Icon</code> to display in the title bar
--- a/jdk/src/java.desktop/share/classes/javax/swing/JLayer.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/share/classes/javax/swing/JLayer.java Wed Jul 05 20:05:54 2017 +0200 @@ -325,24 +325,38 @@ } /** - * A non-{@code null} border, or non-zero insets, isn't supported, to prevent the geometry - * of this component from becoming complex enough to inhibit - * subclassing of {@code LayerUI} class. To create a {@code JLayer} with a border, - * add it to a {@code JPanel} that has a border. - * <p>Note: If {@code border} is non-{@code null}, this - * method will throw an exception as borders are not supported on - * a {@code JLayer}. + * Delegates its functionality to the {@code getView().setBorder(Border)} method, + * if the view component is an instance of {@code javax.swing.JComponent}, + * otherwise this method is a no-op. * - * @param border the {@code Border} to set - * @exception IllegalArgumentException this method is not supported + * @param border the border to be rendered for the {@code view} component + * @see #getView() + * @see javax.swing.JComponent#setBorder(Border) */ public void setBorder(Border border) { - if (border != null) { - throw new IllegalArgumentException("JLayer.setBorder() not supported"); + if (view instanceof JComponent) { + ((JComponent)view).setBorder(border); } } /** + * Delegates its functionality to the {@code getView().getBorder()} method, + * if the view component is an instance of {@code javax.swing.JComponent}, + * otherwise returns {@code null}. + * + * @return the border object for the {@code view} component + * @see #getView() + * @see #setBorder + * @see javax.swing.JComponent#getBorder() + */ + public Border getBorder() { + if (view instanceof JComponent) { + return ((JComponent) view).getBorder(); + } + return null; + } + + /** * This method is not supported by {@code JLayer} * and always throws {@code UnsupportedOperationException} *
--- a/jdk/src/java.desktop/share/classes/javax/swing/border/Border.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/share/classes/javax/swing/border/Border.java Wed Jul 05 20:05:54 2017 +0200 @@ -33,7 +33,7 @@ * Interface describing an object capable of rendering a border * around the edges of a swing component. * For examples of using borders see - * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/border.htmll">How to Use Borders</a>, + * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/border.html">How to Use Borders</a>, * a section in <em>The Java Tutorial.</em> * <p> * In the Swing component set, borders supercede Insets as the
--- a/jdk/src/java.desktop/share/classes/javax/swing/border/package.html Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/share/classes/javax/swing/border/package.html Wed Jul 05 20:05:54 2017 +0200 @@ -40,10 +40,10 @@ Most of the Swing API is <em>not</em> thread safe. For details, see <a -href="http://java.sun.com/docs/books/tutorial/uiswing/overview/threads.html" -target="_top">Threads and Swing</a>, +href="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html" +target="_top">Concurrency in Swing</a>, a section in -<em><a href="http://java.sun.com/docs/books/tutorial/" +<em><a href="http://docs.oracle.com/javase/tutorial/" target="_top">The Java Tutorial</a></em>. @@ -51,7 +51,7 @@ For overviews, tutorials, examples, guides, and tool documentation, please see: <ul> - <li><a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/border.html" + <li><a href="http://docs.oracle.com/javase/tutorial/uiswing/components/border.html" target="_top">How to Use Borders</a>, a section in <em>The Java Tutorial</em> </ul>
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicRadioButtonUI.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicRadioButtonUI.java Wed Jul 05 20:05:54 2017 +0200 @@ -33,7 +33,8 @@ import javax.swing.text.View; import sun.swing.SwingUtilities2; import sun.awt.AppContext; - +import java.util.Enumeration; +import java.util.HashSet; /** * RadioButtonUI implementation for BasicRadioButtonUI @@ -53,6 +54,8 @@ private final static String propertyPrefix = "RadioButton" + "."; + private KeyListener keyListener = null; + // ******************************** // Create PLAF // ******************************** @@ -74,6 +77,7 @@ return radioButtonUI; } + @Override protected String getPropertyPrefix() { return propertyPrefix; } @@ -81,7 +85,8 @@ // ******************************** // Install PLAF // ******************************** - protected void installDefaults(AbstractButton b){ + @Override + protected void installDefaults(AbstractButton b) { super.installDefaults(b); if(!defaults_initialized) { icon = UIManager.getIcon(getPropertyPrefix() + "icon"); @@ -92,7 +97,8 @@ // ******************************** // Uninstall PLAF // ******************************** - protected void uninstallDefaults(AbstractButton b){ + @Override + protected void uninstallDefaults(AbstractButton b) { super.uninstallDefaults(b); defaults_initialized = false; } @@ -106,6 +112,65 @@ return icon; } + // ******************************** + // Install Listeners + // ******************************** + @Override + protected void installListeners(AbstractButton button) { + super.installListeners(button); + + // Only for JRadioButton + if (!(button instanceof JRadioButton)) + return; + + keyListener = createKeyListener(); + button.addKeyListener(keyListener); + + // Need to get traversal key event + button.setFocusTraversalKeysEnabled(false); + + // Map actions to the arrow keys + button.getActionMap().put("Previous", new SelectPreviousBtn()); + button.getActionMap().put("Next", new SelectNextBtn()); + + button.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT). + put(KeyStroke.getKeyStroke("UP"), "Previous"); + button.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT). + put(KeyStroke.getKeyStroke("DOWN"), "Next"); + button.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT). + put(KeyStroke.getKeyStroke("LEFT"), "Previous"); + button.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT). + put(KeyStroke.getKeyStroke("RIGHT"), "Next"); + } + + // ******************************** + // UnInstall Listeners + // ******************************** + @Override + protected void uninstallListeners(AbstractButton button) { + super.uninstallListeners(button); + + // Only for JRadioButton + if (!(button instanceof JRadioButton)) + return; + + // Unmap actions from the arrow keys + button.getActionMap().remove("Previous"); + button.getActionMap().remove("Next"); + button.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) + .remove(KeyStroke.getKeyStroke("UP")); + button.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) + .remove(KeyStroke.getKeyStroke("DOWN")); + button.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) + .remove(KeyStroke.getKeyStroke("LEFT")); + button.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) + .remove(KeyStroke.getKeyStroke("RIGHT")); + + if (keyListener != null) { + button.removeKeyListener(keyListener); + keyListener = null; + } + } /* These Dimensions/Rectangles are allocated once for all * RadioButtonUI.paint() calls. Re-using rectangles @@ -121,6 +186,7 @@ /** * paint the radio button */ + @Override public synchronized void paint(Graphics g, JComponent c) { AbstractButton b = (AbstractButton) c; ButtonModel model = b.getModel(); @@ -217,7 +283,7 @@ * @param textRect bounds * @param size the size of radio button */ - protected void paintFocus(Graphics g, Rectangle textRect, Dimension size){ + protected void paintFocus(Graphics g, Rectangle textRect, Dimension size) { } @@ -235,6 +301,7 @@ /** * The preferred size of the radio button */ + @Override public Dimension getPreferredSize(JComponent c) { if(c.getComponentCount() > 0) { return null; @@ -280,4 +347,262 @@ height += prefInsets.top + prefInsets.bottom; return new Dimension(width, height); } + + /////////////////////////// Private functions //////////////////////// + /** + * Creates the key listener to handle tab navigation in JRadioButton Group. + */ + private KeyListener createKeyListener() { + if (keyListener == null) { + keyListener = new KeyHandler(); + } + return keyListener; + } + + + private boolean isValidRadioButtonObj(Object obj) { + return ((obj instanceof JRadioButton) && + ((JRadioButton) obj).isVisible() && + ((JRadioButton) obj).isEnabled()); + } + + /** + * Select radio button based on "Previous" or "Next" operation + * + * @param event, the event object. + * @param next, indicate if it's next one + */ + private void selectRadioButton(ActionEvent event, boolean next) { + // Get the source of the event. + Object eventSrc = event.getSource(); + + // Check whether the source is JRadioButton, it so, whether it is visible + if (!isValidRadioButtonObj(eventSrc)) + return; + + ButtonGroupInfo btnGroupInfo = new ButtonGroupInfo((JRadioButton)eventSrc); + btnGroupInfo.selectNewButton(next); + } + + /////////////////////////// Inner Classes //////////////////////// + @SuppressWarnings("serial") + private class SelectPreviousBtn extends AbstractAction { + public SelectPreviousBtn() { + super("Previous"); + } + + public void actionPerformed(ActionEvent e) { + BasicRadioButtonUI.this.selectRadioButton(e, false); + } + } + + @SuppressWarnings("serial") + private class SelectNextBtn extends AbstractAction{ + public SelectNextBtn() { + super("Next"); + } + + public void actionPerformed(ActionEvent e) { + BasicRadioButtonUI.this.selectRadioButton(e, true); + } + } + + /** + * ButtonGroupInfo, used to get related info in button group + * for given radio button + */ + private class ButtonGroupInfo { + + JRadioButton activeBtn = null; + + JRadioButton firstBtn = null; + JRadioButton lastBtn = null; + + JRadioButton previousBtn = null; + JRadioButton nextBtn = null; + + HashSet<JRadioButton> btnsInGroup = null; + + boolean srcFound = false; + public ButtonGroupInfo(JRadioButton btn) { + activeBtn = btn; + btnsInGroup = new HashSet<JRadioButton>(); + } + + // Check if given object is in the button group + boolean containsInGroup(Object obj){ + return btnsInGroup.contains(obj); + } + + // Check if the next object to gain focus belongs + // to the button group or not + Component getFocusTransferBaseComponent(boolean next){ + Component focusBaseComp = activeBtn; + Window container = SwingUtilities.getWindowAncestor(activeBtn); + if (container != null) { + FocusTraversalPolicy policy = container.getFocusTraversalPolicy(); + Component comp = next ? policy.getComponentAfter(container, activeBtn) + : policy.getComponentBefore(container, activeBtn); + + // If next component in the button group, use last/first button as base focus + // otherwise, use the activeBtn as the base focus + if (containsInGroup(comp)) { + focusBaseComp = next ? lastBtn : firstBtn; + } + } + + return focusBaseComp; + } + + boolean getButtonGroupInfo() { + if (activeBtn == null) + return false; + + btnsInGroup.clear(); + + // Get the button model from the source. + ButtonModel model = activeBtn.getModel(); + if (!(model instanceof DefaultButtonModel)) + return false; + + // If the button model is DefaultButtonModel, and use it, otherwise return. + DefaultButtonModel bm = (DefaultButtonModel) model; + + // get the ButtonGroup of the button from the button model + ButtonGroup group = bm.getGroup(); + if (group == null) + return false; + + // Get all the buttons in the group + Enumeration<AbstractButton> e = group.getElements(); + if (e == null) + return false; + + while (e.hasMoreElements()) { + AbstractButton curElement = e.nextElement(); + if (!isValidRadioButtonObj(curElement)) + continue; + + btnsInGroup.add((JRadioButton) curElement); + + // If firstBtn is not set yet, curElement is that first button + if (null == firstBtn) + firstBtn = (JRadioButton) curElement; + + if (activeBtn == curElement) + srcFound = true; + else if (!srcFound) { + // The source has not been yet found and the current element + // is the last previousBtn + previousBtn = (JRadioButton) curElement; + } else if (nextBtn == null) { + // The source has been found and the current element + // is the next valid button of the list + nextBtn = (JRadioButton) curElement; + } + + // Set new last "valid" JRadioButton of the list + lastBtn = (JRadioButton) curElement; + } + + return true; + } + + /** + * Find the new radio button that focus needs to be + * moved to in the group, select the button + * + * @param next, indicate if it's arrow up/left or down/right + */ + void selectNewButton(boolean next) { + if (!getButtonGroupInfo()) + return; + + if (srcFound) { + JRadioButton newSelectedBtn = null; + if (next) { + // Select Next button. Cycle to the first button if the source + // button is the last of the group. + newSelectedBtn = (null == nextBtn) ? firstBtn : nextBtn; + } else { + // Select previous button. Cycle to the last button if the source + // button is the first button of the group. + newSelectedBtn = (null == previousBtn) ? lastBtn : previousBtn; + } + if (newSelectedBtn != null && + (newSelectedBtn != activeBtn)) { + newSelectedBtn.requestFocusInWindow(); + newSelectedBtn.setSelected(true); + } + } + } + + /** + * Find the button group the passed in JRadioButton belongs to, and + * move focus to next component of the last button in the group + * or previous component of first button + * + * @param next, indicate if jump to next component or previous + */ + void jumpToNextComponent(boolean next) { + if (!getButtonGroupInfo()){ + // In case the button does not belong to any group, it needs + // to be treated as a component + if (activeBtn != null){ + lastBtn = activeBtn; + firstBtn = activeBtn; + } + else + return; + } + + // Update the component we will use as base to transfer + // focus from + JComponent compTransferFocusFrom = activeBtn; + + // If next component in the parent window is not in + // the button group, current active button will be + // base, otherwise, the base will be first or last + // button in the button group + Component focusBase = getFocusTransferBaseComponent(next); + if (focusBase != null){ + if (next) { + KeyboardFocusManager. + getCurrentKeyboardFocusManager().focusNextComponent(focusBase); + } else { + KeyboardFocusManager. + getCurrentKeyboardFocusManager().focusPreviousComponent(focusBase); + } + } + } + } + + /** + * Radiobutton KeyListener + */ + private class KeyHandler implements KeyListener { + + // This listener checks if the key event is a KeyEvent.VK_TAB + // or shift + KeyEvent.VK_TAB event on a radio button, consume the event + // if so and move the focus to next/previous component + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_TAB) { + // Get the source of the event. + Object eventSrc = e.getSource(); + + // Check whether the source is a visible and enabled JRadioButton + if (isValidRadioButtonObj(eventSrc)) { + e.consume(); + ButtonGroupInfo btnGroupInfo = new ButtonGroupInfo((JRadioButton)eventSrc); + btnGroupInfo.jumpToNextComponent(!e.isShiftDown()); + } + } + } + + public void keyReleased(KeyEvent e) { + } + + public void keyTyped(KeyEvent e) { + } + } }
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java Wed Jul 05 20:05:54 2017 +0200 @@ -3249,6 +3249,7 @@ } } tabScroller.tabPanel.setPreferredSize(new Dimension(totalWidth, totalHeight)); + tabScroller.tabPanel.invalidate(); } } @@ -3622,6 +3623,7 @@ setFocusIndex(tabPane.getSelectedIndex(), false); if (scrollableTabLayoutEnabled()) { + ensureCurrentLayout(); int index = tabPane.getSelectedIndex(); if (index < rects.length && index != -1) { tabScroller.tabPanel.scrollRectToVisible(
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/html/HTMLDocument.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/share/classes/javax/swing/text/html/HTMLDocument.java Wed Jul 05 20:05:54 2017 +0200 @@ -1400,8 +1400,13 @@ Element parent = elem.getParentElement(); if (parent != null) { + // If we are going to insert the string into the body + // section, it is necessary to set the corrsponding flag. + if (HTML.Tag.BODY.name.equals(parent.getName())) { + insertInBody = true; + } int offset = elem.getEndOffset(); - if (offset > getLength()) { + if (offset > (getLength() + 1)) { offset--; } else if (elem.isLeaf() && getText(offset - 1, 1). @@ -1409,6 +1414,10 @@ offset--; } insertHTML(parent, offset, htmlText, false); + // Cleanup the flag, if any. + if (insertInBody) { + insertInBody = false; + } } } } @@ -1847,6 +1856,11 @@ private static char[] NEWLINE; /** + * Indicates that direct insertion to body section takes place. + */ + private boolean insertInBody = false; + + /** * I18N property key. * * @see AbstractDocument#I18NProperty @@ -2610,7 +2624,9 @@ // Assume content should be added. foundInsertTag(false); foundInsertTag = true; - inParagraph = impliedP = true; + // If content is added directly to the body, it should + // be wrapped by p-implied. + inParagraph = impliedP = !insertInBody; } if (data.length >= 1) { addContent(data, 0, data.length);
--- a/jdk/src/java.desktop/share/classes/sun/java2d/opengl/OGLBlitLoops.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/share/classes/sun/java2d/opengl/OGLBlitLoops.java Wed Jul 05 20:05:54 2017 +0200 @@ -47,7 +47,7 @@ import static sun.java2d.pipe.BufferedOpCodes.*; import java.lang.annotation.Native; -class OGLBlitLoops { +final class OGLBlitLoops { static void register() { Blit blitIntArgbPreToSurface = @@ -56,7 +56,9 @@ Blit blitIntArgbPreToTexture = new OGLSwToTextureBlit(SurfaceType.IntArgbPre, OGLSurfaceData.PF_INT_ARGB_PRE); - + TransformBlit transformBlitIntArgbPreToSurface = + new OGLSwToSurfaceTransform(SurfaceType.IntArgbPre, + OGLSurfaceData.PF_INT_ARGB_PRE); GraphicsPrimitive[] primitives = { // surface->surface ops new OGLSurfaceToSurfaceBlit(), @@ -100,7 +102,7 @@ CompositeType.AnyAlpha, blitIntArgbPreToSurface), - new OGLAnyCompositeBlit(OGLSurfaceData.OpenGLSurface), + new OGLAnyCompositeBlit(), new OGLSwToSurfaceScale(SurfaceType.IntRgb, OGLSurfaceData.PF_INT_RGB), @@ -145,8 +147,9 @@ OGLSurfaceData.PF_BYTE_GRAY), new OGLSwToSurfaceTransform(SurfaceType.UshortGray, OGLSurfaceData.PF_USHORT_GRAY), - new OGLSwToSurfaceTransform(SurfaceType.IntArgbPre, - OGLSurfaceData.PF_INT_ARGB_PRE), + transformBlitIntArgbPreToSurface, + + new OGLGeneralTransformedBlit(transformBlitIntArgbPreToSurface), // texture->surface ops new OGLTextureToSurfaceBlit(), @@ -178,9 +181,6 @@ new OGLGeneralBlit(OGLSurfaceData.OpenGLTexture, CompositeType.SrcNoEa, blitIntArgbPreToTexture), - - new OGLAnyCompositeBlit(OGLSurfaceData.OpenGLTexture), - }; GraphicsPrimitiveMgr.register(primitives); } @@ -781,11 +781,11 @@ * This general Blit implementation converts any source surface to an * intermediate IntArgbPre surface, and then uses the more specific * IntArgbPre->OpenGLSurface/Texture loop to get the intermediate - * (premultiplied) surface down to OpenGL. + * (premultiplied) surface down to OpenGL using simple blit. */ class OGLGeneralBlit extends Blit { - private Blit performop; + private final Blit performop; private WeakReference<SurfaceData> srcTmp; OGLGeneralBlit(SurfaceType dstType, @@ -826,12 +826,56 @@ } } -class OGLAnyCompositeBlit extends Blit { +/** + * This general TransformedBlit implementation converts any source surface to an + * intermediate IntArgbPre surface, and then uses the more specific + * IntArgbPre->OpenGLSurface/Texture loop to get the intermediate + * (premultiplied) surface down to OpenGL using simple transformBlit. + */ +final class OGLGeneralTransformedBlit extends TransformBlit { + + private final TransformBlit performop; + private WeakReference<SurfaceData> srcTmp; + + OGLGeneralTransformedBlit(final TransformBlit performop) { + super(SurfaceType.Any, CompositeType.AnyAlpha, + OGLSurfaceData.OpenGLSurface); + this.performop = performop; + } + + @Override + public synchronized void Transform(SurfaceData src, SurfaceData dst, + Composite comp, Region clip, + AffineTransform at, int hint, int srcx, + int srcy, int dstx, int dsty, int width, + int height){ + Blit convertsrc = Blit.getFromCache(src.getSurfaceType(), + CompositeType.SrcNoEa, + SurfaceType.IntArgbPre); + // use cached intermediate surface, if available + final SurfaceData cachedSrc = srcTmp != null ? srcTmp.get() : null; + // convert source to IntArgbPre + src = convertFrom(convertsrc, src, srcx, srcy, width, height, cachedSrc, + BufferedImage.TYPE_INT_ARGB_PRE); + + // transform IntArgbPre intermediate surface to OpenGL surface + performop.Transform(src, dst, comp, clip, at, hint, 0, 0, dstx, dsty, + width, height); + + if (src != cachedSrc) { + // cache the intermediate surface + srcTmp = new WeakReference<>(src); + } + } +} + +final class OGLAnyCompositeBlit extends Blit { private WeakReference<SurfaceData> dstTmp; - public OGLAnyCompositeBlit(SurfaceType dstType) { - super(SurfaceType.Any, CompositeType.Any, dstType); + OGLAnyCompositeBlit() { + super(SurfaceType.Any, CompositeType.Any, OGLSurfaceData.OpenGLSurface); } + public synchronized void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, @@ -848,15 +892,15 @@ cachedDst = dstTmp.get(); } - // convert source to IntArgbPre + // convert destination to IntArgbPre SurfaceData dstBuffer = convertFrom(convertdst, dst, dx, dy, w, h, cachedDst, BufferedImage.TYPE_INT_ARGB_PRE); + Region bufferClip = + clip == null ? null : clip.getTranslatedRegion(-dx, -dy); Blit performop = Blit.getFromCache(src.getSurfaceType(), CompositeType.Any, dstBuffer.getSurfaceType()); - - performop.Blit(src, dstBuffer, comp, clip, - sx, sy, 0, 0, w, h); + performop.Blit(src, dstBuffer, comp, bufferClip, sx, sy, 0, 0, w, h); if (dstBuffer != cachedDst) { // cache the intermediate surface
--- a/jdk/src/java.desktop/unix/classes/META-INF/services/javax.print.PrintServiceLookup Thu Oct 30 08:34:51 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -# Provider for Java Print Service -sun.print.UnixPrintServiceLookup
--- a/jdk/src/java.desktop/unix/classes/META-INF/services/javax.print.StreamPrintServiceFactory Thu Oct 30 08:34:51 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -# Provider for Java 2D Stream print services. -sun.print.PSStreamPrinterFactory
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWM.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWM.java Wed Jul 05 20:05:54 2017 +0200 @@ -595,8 +595,13 @@ return isNetWMName("Mutter") || isNetWMName("GNOME Shell"); } + static int awtWMNonReparenting = -1; static boolean isNonReparentingWM() { - return (XWM.getWMID() == XWM.COMPIZ_WM || XWM.getWMID() == XWM.LG3D_WM || XWM.getWMID() == XWM.CWM_WM); + if (awtWMNonReparenting == -1) { + awtWMNonReparenting = (XToolkit.getEnv("_JAVA_AWT_WM_NONREPARENTING") != null) ? 1 : 0; + } + return (awtWMNonReparenting == 1 || XWM.getWMID() == XWM.COMPIZ_WM + || XWM.getWMID() == XWM.LG3D_WM || XWM.getWMID() == XWM.CWM_WM); } /*
--- a/jdk/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java Wed Jul 05 20:05:54 2017 +0200 @@ -324,8 +324,8 @@ * reported, exec lpstat -d which has all the Apple * special behaviour for this built in. */ - if (UnixPrintServiceLookup.isMac()) { - printerInfo[0] = UnixPrintServiceLookup. + if (PrintServiceLookupProvider.isMac()) { + printerInfo[0] = PrintServiceLookupProvider. getDefaultPrinterNameSysV(); printerInfo[1] = null; return printerInfo.clone();
--- a/jdk/src/java.desktop/unix/classes/sun/print/IPPPrintService.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/unix/classes/sun/print/IPPPrintService.java Wed Jul 05 20:05:54 2017 +0200 @@ -1047,7 +1047,7 @@ setting like collation. Therefore, we temporarily exclude Linux. */ - if (!UnixPrintServiceLookup.isLinux()) { + if (!PrintServiceLookupProvider.isLinux()) { catList.add(SheetCollate.class); } } @@ -1641,7 +1641,7 @@ * Mac is using printer-info IPP attribute for its human-readable printer * name and is also the identifier used in NSPrintInfo:setPrinter. */ - if (UnixPrintServiceLookup.isMac()) { + if (PrintServiceLookupProvider.isMac()) { PrintServiceAttributeSet psaSet = this.getAttributes(); if (psaSet != null) { PrinterInfo pName = (PrinterInfo)psaSet.get(PrinterInfo.class);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java Wed Jul 05 20:05:54 2017 +0200 @@ -0,0 +1,964 @@ +/* + * Copyright (c) 2000, 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.print; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Vector; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import javax.print.DocFlavor; +import javax.print.MultiDocPrintService; +import javax.print.PrintService; +import javax.print.PrintServiceLookup; +import javax.print.attribute.Attribute; +import javax.print.attribute.AttributeSet; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.HashPrintServiceAttributeSet; +import javax.print.attribute.PrintRequestAttribute; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.PrintServiceAttribute; +import javax.print.attribute.PrintServiceAttributeSet; +import javax.print.attribute.standard.PrinterName; +import javax.print.attribute.standard.PrinterURI; +import java.io.File; +import java.io.FileReader; +import java.net.URL; +import java.nio.file.Files; + +/* + * Remind: This class uses solaris commands. We also need a linux + * version + */ +public class PrintServiceLookupProvider extends PrintServiceLookup + implements BackgroundServiceLookup, Runnable { + + /* Remind: the current implementation is static, as its assumed + * its preferable to minimize creation of PrintService instances. + * Later we should add logic to add/remove services on the fly which + * will take a hit of needing to regather the list of services. + */ + private String defaultPrinter; + private PrintService defaultPrintService; + private PrintService[] printServices; /* includes the default printer */ + private Vector<BackgroundLookupListener> lookupListeners = null; + private static String debugPrefix = "PrintServiceLookupProvider>> "; + private static boolean pollServices = true; + private static final int DEFAULT_MINREFRESH = 120; // 2 minutes + private static int minRefreshTime = DEFAULT_MINREFRESH; + + + static String osname; + + // List of commands used to deal with the printer queues on AIX + String[] lpNameComAix = { + "/usr/bin/lsallq", + "/usr/bin/lpstat -W -p|/usr/bin/expand|/usr/bin/cut -f1 -d' '", + "/usr/bin/lpstat -W -d|/usr/bin/expand|/usr/bin/cut -f1 -d' '", + "/usr/bin/lpstat -W -v" + }; + private static final int aix_lsallq = 0; + private static final int aix_lpstat_p = 1; + private static final int aix_lpstat_d = 2; + private static final int aix_lpstat_v = 3; + private static int aix_defaultPrinterEnumeration = aix_lsallq; + + static { + /* The system property "sun.java2d.print.polling" + * can be used to force the printing code to poll or not poll + * for PrintServices. + */ + String pollStr = java.security.AccessController.doPrivileged( + new sun.security.action.GetPropertyAction("sun.java2d.print.polling")); + + if (pollStr != null) { + if (pollStr.equalsIgnoreCase("true")) { + pollServices = true; + } else if (pollStr.equalsIgnoreCase("false")) { + pollServices = false; + } + } + + /* The system property "sun.java2d.print.minRefreshTime" + * can be used to specify minimum refresh time (in seconds) + * for polling PrintServices. The default is 120. + */ + String refreshTimeStr = java.security.AccessController.doPrivileged( + new sun.security.action.GetPropertyAction( + "sun.java2d.print.minRefreshTime")); + + if (refreshTimeStr != null) { + try { + minRefreshTime = (new Integer(refreshTimeStr)).intValue(); + } catch (NumberFormatException e) { + } + if (minRefreshTime < DEFAULT_MINREFRESH) { + minRefreshTime = DEFAULT_MINREFRESH; + } + } + + osname = java.security.AccessController.doPrivileged( + new sun.security.action.GetPropertyAction("os.name")); + + /* The system property "sun.java2d.print.aix.lpstat" + * can be used to force the usage of 'lpstat -p' to enumerate all + * printer queues. By default we use 'lsallq', because 'lpstat -p' can + * take lots of time if thousands of printers are attached to a server. + */ + if (isAIX()) { + String aixPrinterEnumerator = java.security.AccessController.doPrivileged( + new sun.security.action.GetPropertyAction("sun.java2d.print.aix.lpstat")); + + if (aixPrinterEnumerator != null) { + if (aixPrinterEnumerator.equalsIgnoreCase("lpstat")) { + aix_defaultPrinterEnumeration = aix_lpstat_p; + } else if (aixPrinterEnumerator.equalsIgnoreCase("lsallq")) { + aix_defaultPrinterEnumeration = aix_lsallq; + } + } + } + } + + static boolean isMac() { + return osname.startsWith("Mac"); + } + + static boolean isSysV() { + return osname.equals("SunOS"); + } + + static boolean isLinux() { + return (osname.equals("Linux")); + } + + static boolean isBSD() { + return (osname.equals("Linux") || + osname.contains("OS X")); + } + + static boolean isAIX() { + return osname.equals("AIX"); + } + + static final int UNINITIALIZED = -1; + static final int BSD_LPD = 0; + static final int BSD_LPD_NG = 1; + + static int cmdIndex = UNINITIALIZED; + + String[] lpcFirstCom = { + "/usr/sbin/lpc status | grep : | sed -ne '1,1 s/://p'", + "/usr/sbin/lpc status | grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}'" + }; + + String[] lpcAllCom = { + "/usr/sbin/lpc status all | grep : | sed -e 's/://'", + "/usr/sbin/lpc status all | grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}' | sort" + }; + + String[] lpcNameCom = { + "| grep : | sed -ne 's/://p'", + "| grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}'" + }; + + + static int getBSDCommandIndex() { + String command = "/usr/sbin/lpc status all"; + String[] names = execCmd(command); + + if ((names == null) || (names.length == 0)) { + return BSD_LPD_NG; + } + + for (int i=0; i<names.length; i++) { + if (names[i].indexOf('@') != -1) { + return BSD_LPD_NG; + } + } + + return BSD_LPD; + } + + + public PrintServiceLookupProvider() { + // start the printer listener thread + if (pollServices) { + PrinterChangeListener thr = new PrinterChangeListener(); + thr.setDaemon(true); + thr.start(); + IPPPrintService.debug_println(debugPrefix+"polling turned on"); + } + } + + /* Want the PrintService which is default print service to have + * equality of reference with the equivalent in list of print services + * This isn't required by the API and there's a risk doing this will + * lead people to assume its guaranteed. + */ + public synchronized PrintService[] getPrintServices() { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkPrintJobAccess(); + } + + if (printServices == null || !pollServices) { + refreshServices(); + } + if (printServices == null) { + return new PrintService[0]; + } else { + return printServices.clone(); + } + } + + private int addPrintServiceToList(ArrayList<PrintService> printerList, PrintService ps) { + int index = printerList.indexOf(ps); + // Check if PrintService with same name is already in the list. + if (CUPSPrinter.isCupsRunning() && index != -1) { + // Bug in Linux: Duplicate entry of a remote printer + // and treats it as local printer but it is returning wrong + // information when queried using IPP. Workaround is to remove it. + // Even CUPS ignores these entries as shown in lpstat or using + // their web configuration. + PrinterURI uri = ps.getAttribute(PrinterURI.class); + if (uri.getURI().getHost().equals("localhost")) { + IPPPrintService.debug_println(debugPrefix+"duplicate PrintService, ignoring the new local printer: "+ps); + return index; // Do not add this. + } + PrintService oldPS = printerList.get(index); + uri = oldPS.getAttribute(PrinterURI.class); + if (uri.getURI().getHost().equals("localhost")) { + IPPPrintService.debug_println(debugPrefix+"duplicate PrintService, removing existing local printer: "+oldPS); + printerList.remove(oldPS); + } else { + return index; + } + } + printerList.add(ps); + return (printerList.size() - 1); + } + + + // refreshes "printServices" + public synchronized void refreshServices() { + /* excludes the default printer */ + String[] printers = null; // array of printer names + String[] printerURIs = null; //array of printer URIs + + try { + getDefaultPrintService(); + } catch (Throwable t) { + IPPPrintService.debug_println(debugPrefix+ + "Exception getting default printer : " + t); + } + if (CUPSPrinter.isCupsRunning()) { + try { + printerURIs = CUPSPrinter.getAllPrinters(); + IPPPrintService.debug_println("CUPS URIs = " + printerURIs); + if (printerURIs != null) { + for (int p = 0; p < printerURIs.length; p++) { + IPPPrintService.debug_println("URI="+printerURIs[p]); + } + } + } catch (Throwable t) { + IPPPrintService.debug_println(debugPrefix+ + "Exception getting all CUPS printers : " + t); + } + if ((printerURIs != null) && (printerURIs.length > 0)) { + printers = new String[printerURIs.length]; + for (int i=0; i<printerURIs.length; i++) { + int lastIndex = printerURIs[i].lastIndexOf("/"); + printers[i] = printerURIs[i].substring(lastIndex+1); + } + } + } else { + if (isMac() || isSysV()) { + printers = getAllPrinterNamesSysV(); + } else if (isAIX()) { + printers = getAllPrinterNamesAIX(); + } else { //BSD + printers = getAllPrinterNamesBSD(); + } + } + + if (printers == null) { + if (defaultPrintService != null) { + printServices = new PrintService[1]; + printServices[0] = defaultPrintService; + } else { + printServices = null; + } + return; + } + + ArrayList<PrintService> printerList = new ArrayList<>(); + int defaultIndex = -1; + for (int p=0; p<printers.length; p++) { + if (printers[p] == null) { + continue; + } + if ((defaultPrintService != null) + && printers[p].equals(getPrinterDestName(defaultPrintService))) { + defaultIndex = addPrintServiceToList(printerList, defaultPrintService); + } else { + if (printServices == null) { + IPPPrintService.debug_println(debugPrefix+ + "total# of printers = "+printers.length); + + if (CUPSPrinter.isCupsRunning()) { + try { + addPrintServiceToList(printerList, + new IPPPrintService(printers[p], + printerURIs[p], + true)); + } catch (Exception e) { + IPPPrintService.debug_println(debugPrefix+ + " getAllPrinters Exception "+ + e); + + } + } else { + printerList.add(new UnixPrintService(printers[p])); + } + } else { + int j; + for (j=0; j<printServices.length; j++) { + if (printServices[j] != null) { + if (printers[p].equals(getPrinterDestName(printServices[j]))) { + printerList.add(printServices[j]); + printServices[j] = null; + break; + } + } + } + + if (j == printServices.length) { // not found? + if (CUPSPrinter.isCupsRunning()) { + try { + addPrintServiceToList(printerList, + new IPPPrintService(printers[p], + printerURIs[p], + true)); + } catch (Exception e) { + IPPPrintService.debug_println(debugPrefix+ + " getAllPrinters Exception "+ + e); + + } + } else { + printerList.add(new UnixPrintService(printers[p])); + } + } + } + } + } + + // Look for deleted services and invalidate these + if (printServices != null) { + for (int j=0; j < printServices.length; j++) { + if ((printServices[j] instanceof UnixPrintService) && + (!printServices[j].equals(defaultPrintService))) { + ((UnixPrintService)printServices[j]).invalidateService(); + } + } + } + + //if defaultService is not found in printerList + if (defaultIndex == -1 && defaultPrintService != null) { + defaultIndex = addPrintServiceToList(printerList, defaultPrintService); + } + + printServices = printerList.toArray(new PrintService[] {}); + + // swap default with the first in the list + if (defaultIndex > 0) { + PrintService saveService = printServices[0]; + printServices[0] = printServices[defaultIndex]; + printServices[defaultIndex] = saveService; + } + } + + private boolean matchesAttributes(PrintService service, + PrintServiceAttributeSet attributes) { + + Attribute [] attrs = attributes.toArray(); + for (int i=0; i<attrs.length; i++) { + @SuppressWarnings("unchecked") + Attribute serviceAttr + = service.getAttribute((Class<PrintServiceAttribute>)attrs[i].getCategory()); + if (serviceAttr == null || !serviceAttr.equals(attrs[i])) { + return false; + } + } + return true; + } + + /* This checks for validity of the printer name before passing as + * parameter to a shell command. + */ + private boolean checkPrinterName(String s) { + char c; + + for (int i=0; i < s.length(); i++) { + c = s.charAt(i); + if (Character.isLetterOrDigit(c) || + c == '-' || c == '_' || c == '.' || c == '/') { + continue; + } else { + return false; + } + } + return true; + } + + /* + * Gets the printer name compatible with the list of printers returned by + * the system when we query default or all the available printers. + */ + private String getPrinterDestName(PrintService ps) { + if (isMac()) { + return ((IPPPrintService)ps).getDest(); + } + return ps.getName(); + } + + /* On a network with many (hundreds) of network printers, it + * can save several seconds if you know all you want is a particular + * printer, to ask for that printer rather than retrieving all printers. + */ + private PrintService getServiceByName(PrinterName nameAttr) { + String name = nameAttr.getValue(); + if (name == null || name.equals("") || !checkPrinterName(name)) { + return null; + } + /* check if all printers are already available */ + if (printServices != null) { + for (PrintService printService : printServices) { + PrinterName printerName = printService.getAttribute(PrinterName.class); + if (printerName.getValue().equals(name)) { + return printService; + } + } + } + /* take CUPS into account first */ + if (CUPSPrinter.isCupsRunning()) { + try { + return new IPPPrintService(name, + new URL("http://"+ + CUPSPrinter.getServer()+":"+ + CUPSPrinter.getPort()+"/"+ + name)); + } catch (Exception e) { + IPPPrintService.debug_println(debugPrefix+ + " getServiceByName Exception "+ + e); + } + } + /* fallback if nothing not having a printer at this point */ + PrintService printer = null; + if (isMac() || isSysV()) { + printer = getNamedPrinterNameSysV(name); + } else if (isAIX()) { + printer = getNamedPrinterNameAIX(name); + } else { + printer = getNamedPrinterNameBSD(name); + } + return printer; + } + + private PrintService[] + getPrintServices(PrintServiceAttributeSet serviceSet) { + + if (serviceSet == null || serviceSet.isEmpty()) { + return getPrintServices(); + } + + /* Typically expect that if a service attribute is specified that + * its a printer name and there ought to be only one match. + * Directly retrieve that service and confirm + * that it meets the other requirements. + * If printer name isn't mentioned then go a slow path checking + * all printers if they meet the reqiremements. + */ + PrintService[] services; + PrinterName name = (PrinterName)serviceSet.get(PrinterName.class); + PrintService defService; + if (name != null && (defService = getDefaultPrintService()) != null) { + /* To avoid execing a unix command see if the client is asking + * for the default printer by name, since we already have that + * initialised. + */ + + PrinterName defName = defService.getAttribute(PrinterName.class); + + if (defName != null && name.equals(defName)) { + if (matchesAttributes(defService, serviceSet)) { + services = new PrintService[1]; + services[0] = defService; + return services; + } else { + return new PrintService[0]; + } + } else { + /* Its not the default service */ + PrintService service = getServiceByName(name); + if (service != null && + matchesAttributes(service, serviceSet)) { + services = new PrintService[1]; + services[0] = service; + return services; + } else { + return new PrintService[0]; + } + } + } else { + /* specified service attributes don't include a name.*/ + Vector<PrintService> matchedServices = new Vector<>(); + services = getPrintServices(); + for (int i = 0; i< services.length; i++) { + if (matchesAttributes(services[i], serviceSet)) { + matchedServices.add(services[i]); + } + } + services = new PrintService[matchedServices.size()]; + for (int i = 0; i< services.length; i++) { + services[i] = matchedServices.elementAt(i); + } + return services; + } + } + + /* + * If service attributes are specified then there must be additional + * filtering. + */ + public PrintService[] getPrintServices(DocFlavor flavor, + AttributeSet attributes) { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkPrintJobAccess(); + } + PrintRequestAttributeSet requestSet = null; + PrintServiceAttributeSet serviceSet = null; + + if (attributes != null && !attributes.isEmpty()) { + + requestSet = new HashPrintRequestAttributeSet(); + serviceSet = new HashPrintServiceAttributeSet(); + + Attribute[] attrs = attributes.toArray(); + for (int i=0; i<attrs.length; i++) { + if (attrs[i] instanceof PrintRequestAttribute) { + requestSet.add(attrs[i]); + } else if (attrs[i] instanceof PrintServiceAttribute) { + serviceSet.add(attrs[i]); + } + } + } + + PrintService[] services = getPrintServices(serviceSet); + if (services.length == 0) { + return services; + } + + if (CUPSPrinter.isCupsRunning()) { + ArrayList<PrintService> matchingServices = new ArrayList<>(); + for (int i=0; i<services.length; i++) { + try { + if (services[i]. + getUnsupportedAttributes(flavor, requestSet) == null) { + matchingServices.add(services[i]); + } + } catch (IllegalArgumentException e) { + } + } + services = new PrintService[matchingServices.size()]; + return matchingServices.toArray(services); + + } else { + // We only need to compare 1 PrintService because all + // UnixPrintServices are the same anyway. We will not use + // default PrintService because it might be null. + PrintService service = services[0]; + if ((flavor == null || + service.isDocFlavorSupported(flavor)) && + service.getUnsupportedAttributes(flavor, requestSet) == null) + { + return services; + } else { + return new PrintService[0]; + } + } + } + + /* + * return empty array as don't support multi docs + */ + public MultiDocPrintService[] + getMultiDocPrintServices(DocFlavor[] flavors, + AttributeSet attributes) { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkPrintJobAccess(); + } + return new MultiDocPrintService[0]; + } + + + public synchronized PrintService getDefaultPrintService() { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkPrintJobAccess(); + } + + // clear defaultPrintService + defaultPrintService = null; + String psuri = null; + + IPPPrintService.debug_println("isRunning ? "+ + (CUPSPrinter.isCupsRunning())); + if (CUPSPrinter.isCupsRunning()) { + String[] printerInfo = CUPSPrinter.getDefaultPrinter(); + if (printerInfo != null && printerInfo.length >= 2) { + defaultPrinter = printerInfo[0]; + psuri = printerInfo[1]; + } + } else { + if (isMac() || isSysV()) { + defaultPrinter = getDefaultPrinterNameSysV(); + } else if (isAIX()) { + defaultPrinter = getDefaultPrinterNameAIX(); + } else { + defaultPrinter = getDefaultPrinterNameBSD(); + } + } + if (defaultPrinter == null) { + return null; + } + defaultPrintService = null; + if (printServices != null) { + for (int j=0; j<printServices.length; j++) { + if (defaultPrinter.equals(getPrinterDestName(printServices[j]))) { + defaultPrintService = printServices[j]; + break; + } + } + } + if (defaultPrintService == null) { + if (CUPSPrinter.isCupsRunning()) { + try { + PrintService defaultPS; + if ((psuri != null) && !psuri.startsWith("file")) { + defaultPS = new IPPPrintService(defaultPrinter, + psuri, true); + } else { + defaultPS = new IPPPrintService(defaultPrinter, + new URL("http://"+ + CUPSPrinter.getServer()+":"+ + CUPSPrinter.getPort()+"/"+ + defaultPrinter)); + } + defaultPrintService = defaultPS; + } catch (Exception e) { + } + } else { + defaultPrintService = new UnixPrintService(defaultPrinter); + } + } + + return defaultPrintService; + } + + public synchronized void + getServicesInbackground(BackgroundLookupListener listener) { + if (printServices != null) { + listener.notifyServices(printServices); + } else { + if (lookupListeners == null) { + lookupListeners = new Vector<>(); + lookupListeners.add(listener); + Thread lookupThread = new Thread(this); + lookupThread.start(); + } else { + lookupListeners.add(listener); + } + } + } + + /* This method isn't used in most cases because we rely on code in + * javax.print.PrintServiceLookup. This is needed just for the cases + * where those interfaces are by-passed. + */ + private PrintService[] copyOf(PrintService[] inArr) { + if (inArr == null || inArr.length == 0) { + return inArr; + } else { + PrintService []outArr = new PrintService[inArr.length]; + System.arraycopy(inArr, 0, outArr, 0, inArr.length); + return outArr; + } + } + + public void run() { + PrintService[] services = getPrintServices(); + synchronized (this) { + BackgroundLookupListener listener; + for (int i=0; i<lookupListeners.size(); i++) { + listener = lookupListeners.elementAt(i); + listener.notifyServices(copyOf(services)); + } + lookupListeners = null; + } + } + + private String getDefaultPrinterNameBSD() { + if (cmdIndex == UNINITIALIZED) { + cmdIndex = getBSDCommandIndex(); + } + String[] names = execCmd(lpcFirstCom[cmdIndex]); + if (names == null || names.length == 0) { + return null; + } + + if ((cmdIndex==BSD_LPD_NG) && + (names[0].startsWith("missingprinter"))) { + return null; + } + return names[0]; + } + + private PrintService getNamedPrinterNameBSD(String name) { + if (cmdIndex == UNINITIALIZED) { + cmdIndex = getBSDCommandIndex(); + } + String command = "/usr/sbin/lpc status " + name + lpcNameCom[cmdIndex]; + String[] result = execCmd(command); + + if (result == null || !(result[0].equals(name))) { + return null; + } + return new UnixPrintService(name); + } + + private String[] getAllPrinterNamesBSD() { + if (cmdIndex == UNINITIALIZED) { + cmdIndex = getBSDCommandIndex(); + } + String[] names = execCmd(lpcAllCom[cmdIndex]); + if (names == null || names.length == 0) { + return null; + } + return names; + } + + static String getDefaultPrinterNameSysV() { + String defaultPrinter = "lp"; + String command = "/usr/bin/lpstat -d"; + + String [] names = execCmd(command); + if (names == null || names.length == 0) { + return defaultPrinter; + } else { + int index = names[0].indexOf(":"); + if (index == -1 || (names[0].length() <= index+1)) { + return null; + } else { + String name = names[0].substring(index+1).trim(); + if (name.length() == 0) { + return null; + } else { + return name; + } + } + } + } + + private PrintService getNamedPrinterNameSysV(String name) { + + String command = "/usr/bin/lpstat -v " + name; + String []result = execCmd(command); + + if (result == null || result[0].indexOf("unknown printer") > 0) { + return null; + } else { + return new UnixPrintService(name); + } + } + + private String[] getAllPrinterNamesSysV() { + String defaultPrinter = "lp"; + String command = "/usr/bin/lpstat -v|/usr/bin/expand|/usr/bin/cut -f3 -d' ' |/usr/bin/cut -f1 -d':' | /usr/bin/sort"; + + String [] names = execCmd(command); + ArrayList<String> printerNames = new ArrayList<>(); + for (int i=0; i < names.length; i++) { + if (!names[i].equals("_default") && + !names[i].equals(defaultPrinter) && + !names[i].equals("")) { + printerNames.add(names[i]); + } + } + return printerNames.toArray(new String[printerNames.size()]); + } + + private String getDefaultPrinterNameAIX() { + String[] names = execCmd(lpNameComAix[aix_lpstat_d]); + // Remove headers and bogus entries added by remote printers. + names = UnixPrintService.filterPrinterNamesAIX(names); + if (names == null || names.length != 1) { + // No default printer found + return null; + } else { + return names[0]; + } + } + + private PrintService getNamedPrinterNameAIX(String name) { + // On AIX there should be no blank after '-v'. + String[] result = execCmd(lpNameComAix[aix_lpstat_v] + name); + // Remove headers and bogus entries added by remote printers. + result = UnixPrintService.filterPrinterNamesAIX(result); + if (result == null || result.length != 1) { + return null; + } else { + return new UnixPrintService(name); + } + } + + private String[] getAllPrinterNamesAIX() { + // Determine all printers of the system. + String [] names = execCmd(lpNameComAix[aix_defaultPrinterEnumeration]); + + // Remove headers and bogus entries added by remote printers. + names = UnixPrintService.filterPrinterNamesAIX(names); + + ArrayList<String> printerNames = new ArrayList<String>(); + for ( int i=0; i < names.length; i++) { + printerNames.add(names[i]); + } + return printerNames.toArray(new String[printerNames.size()]); + } + + static String[] execCmd(final String command) { + ArrayList<String> results = null; + try { + final String[] cmd = new String[3]; + if (isSysV() || isAIX()) { + cmd[0] = "/usr/bin/sh"; + cmd[1] = "-c"; + cmd[2] = "env LC_ALL=C " + command; + } else { + cmd[0] = "/bin/sh"; + cmd[1] = "-c"; + cmd[2] = "LC_ALL=C " + command; + } + + results = AccessController.doPrivileged( + new PrivilegedExceptionAction<ArrayList<String>>() { + public ArrayList<String> run() throws IOException { + + Process proc; + BufferedReader bufferedReader = null; + File f = Files.createTempFile("prn","xc").toFile(); + cmd[2] = cmd[2]+">"+f.getAbsolutePath(); + + proc = Runtime.getRuntime().exec(cmd); + try { + boolean done = false; // in case of interrupt. + while (!done) { + try { + proc.waitFor(); + done = true; + } catch (InterruptedException e) { + } + } + + if (proc.exitValue() == 0) { + FileReader reader = new FileReader(f); + bufferedReader = new BufferedReader(reader); + String line; + ArrayList<String> results = new ArrayList<>(); + while ((line = bufferedReader.readLine()) + != null) { + results.add(line); + } + return results; + } + } finally { + f.delete(); + // promptly close all streams. + if (bufferedReader != null) { + bufferedReader.close(); + } + proc.getInputStream().close(); + proc.getErrorStream().close(); + proc.getOutputStream().close(); + } + return null; + } + }); + } catch (PrivilegedActionException e) { + } + if (results == null) { + return new String[0]; + } else { + return results.toArray(new String[results.size()]); + } + } + + private class PrinterChangeListener extends Thread { + + public void run() { + int refreshSecs; + while (true) { + try { + refreshServices(); + } catch (Exception se) { + IPPPrintService.debug_println(debugPrefix+"Exception in refresh thread."); + break; + } + + if ((printServices != null) && + (printServices.length > minRefreshTime)) { + // compute new refresh time 1 printer = 1 sec + refreshSecs = printServices.length; + } else { + refreshSecs = minRefreshTime; + } + try { + sleep(refreshSecs * 1000); + } catch (InterruptedException e) { + break; + } + } + } + } +}
--- a/jdk/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java Wed Jul 05 20:05:54 2017 +0200 @@ -122,7 +122,7 @@ UnixPrintJob(PrintService service) { this.service = service; mDestination = service.getName(); - if (UnixPrintServiceLookup.isMac()) { + if (PrintServiceLookupProvider.isMac()) { mDestination = ((IPPPrintService)service).getDest(); } mDestType = UnixPrintJob.DESTPRINTER; @@ -880,7 +880,7 @@ pFlags |= NOSHEET; ncomps+=1; } - if (UnixPrintServiceLookup.osname.equals("SunOS")) { + if (PrintServiceLookupProvider.osname.equals("SunOS")) { ncomps+=1; // lp uses 1 more arg than lpr (make a copy) execCmd = new String[ncomps]; execCmd[n++] = "/usr/bin/lp";
--- a/jdk/src/java.desktop/unix/classes/sun/print/UnixPrintService.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/unix/classes/sun/print/UnixPrintService.java Wed Jul 05 20:05:54 2017 +0200 @@ -220,7 +220,7 @@ private PrinterIsAcceptingJobs getPrinterIsAcceptingJobsSysV() { String command = "/usr/bin/lpstat -a " + printer; - String results[]= UnixPrintServiceLookup.execCmd(command); + String results[]= PrintServiceLookupProvider.execCmd(command); if (results != null && results.length > 0) { if (results[0].startsWith(printer + " accepting requests")) { @@ -244,20 +244,20 @@ } private PrinterIsAcceptingJobs getPrinterIsAcceptingJobsBSD() { - if (UnixPrintServiceLookup.cmdIndex == - UnixPrintServiceLookup.UNINITIALIZED) { + if (PrintServiceLookupProvider.cmdIndex == + PrintServiceLookupProvider.UNINITIALIZED) { - UnixPrintServiceLookup.cmdIndex = - UnixPrintServiceLookup.getBSDCommandIndex(); + PrintServiceLookupProvider.cmdIndex = + PrintServiceLookupProvider.getBSDCommandIndex(); } String command = "/usr/sbin/lpc status " + printer - + lpcStatusCom[UnixPrintServiceLookup.cmdIndex]; - String results[]= UnixPrintServiceLookup.execCmd(command); + + lpcStatusCom[PrintServiceLookupProvider.cmdIndex]; + String results[]= PrintServiceLookupProvider.execCmd(command); if (results != null && results.length > 0) { - if (UnixPrintServiceLookup.cmdIndex == - UnixPrintServiceLookup.BSD_LPD_NG) { + if (PrintServiceLookupProvider.cmdIndex == + PrintServiceLookupProvider.BSD_LPD_NG) { if (results[0].startsWith("enabled enabled")) { return PrinterIsAcceptingJobs.ACCEPTING_JOBS ; } @@ -276,7 +276,7 @@ // Filter the list of possible AIX Printers and remove header lines // and extra lines which have been added for remote printers. - // 'protected' because this method is also used from UnixPrintServiceLookup. + // 'protected' because this method is also used from PrintServiceLookupProvider. protected static String[] filterPrinterNamesAIX(String[] posPrinters) { ArrayList<String> printers = new ArrayList<>(); String [] splitPart; @@ -301,7 +301,7 @@ private PrinterIsAcceptingJobs getPrinterIsAcceptingJobsAIX() { // On AIX there should not be a blank after '-a'. String command = "/usr/bin/lpstat -a" + printer; - String results[]= UnixPrintServiceLookup.execCmd(command); + String results[]= PrintServiceLookupProvider.execCmd(command); // Remove headers and bogus entries added by remote printers. results = filterPrinterNamesAIX(results); @@ -320,11 +320,11 @@ } private PrinterIsAcceptingJobs getPrinterIsAcceptingJobs() { - if (UnixPrintServiceLookup.isSysV()) { + if (PrintServiceLookupProvider.isSysV()) { return getPrinterIsAcceptingJobsSysV(); - } else if (UnixPrintServiceLookup.isBSD()) { + } else if (PrintServiceLookupProvider.isBSD()) { return getPrinterIsAcceptingJobsBSD(); - } else if (UnixPrintServiceLookup.isAIX()) { + } else if (PrintServiceLookupProvider.isAIX()) { return getPrinterIsAcceptingJobsAIX(); } else { return PrinterIsAcceptingJobs.ACCEPTING_JOBS; @@ -351,29 +351,29 @@ private QueuedJobCount getQueuedJobCountSysV() { String command = "/usr/bin/lpstat -R " + printer; - String results[]= UnixPrintServiceLookup.execCmd(command); + String results[]= PrintServiceLookupProvider.execCmd(command); int qlen = (results == null) ? 0 : results.length; return new QueuedJobCount(qlen); } private QueuedJobCount getQueuedJobCountBSD() { - if (UnixPrintServiceLookup.cmdIndex == - UnixPrintServiceLookup.UNINITIALIZED) { + if (PrintServiceLookupProvider.cmdIndex == + PrintServiceLookupProvider.UNINITIALIZED) { - UnixPrintServiceLookup.cmdIndex = - UnixPrintServiceLookup.getBSDCommandIndex(); + PrintServiceLookupProvider.cmdIndex = + PrintServiceLookupProvider.getBSDCommandIndex(); } int qlen = 0; String command = "/usr/sbin/lpc status " + printer - + lpcQueueCom[UnixPrintServiceLookup.cmdIndex]; - String results[] = UnixPrintServiceLookup.execCmd(command); + + lpcQueueCom[PrintServiceLookupProvider.cmdIndex]; + String results[] = PrintServiceLookupProvider.execCmd(command); if (results != null && results.length > 0) { String queued; - if (UnixPrintServiceLookup.cmdIndex == - UnixPrintServiceLookup.BSD_LPD_NG) { + if (PrintServiceLookupProvider.cmdIndex == + PrintServiceLookupProvider.BSD_LPD_NG) { queued = results[0]; } else { queued = results[3].trim(); @@ -396,7 +396,7 @@ private QueuedJobCount getQueuedJobCountAIX() { // On AIX there should not be a blank after '-a'. String command = "/usr/bin/lpstat -a" + printer; - String results[]= UnixPrintServiceLookup.execCmd(command); + String results[]= PrintServiceLookupProvider.execCmd(command); // Remove headers and bogus entries added by remote printers. results = filterPrinterNamesAIX(results); @@ -413,11 +413,11 @@ } private QueuedJobCount getQueuedJobCount() { - if (UnixPrintServiceLookup.isSysV()) { + if (PrintServiceLookupProvider.isSysV()) { return getQueuedJobCountSysV(); - } else if (UnixPrintServiceLookup.isBSD()) { + } else if (PrintServiceLookupProvider.isBSD()) { return getQueuedJobCountBSD(); - } else if (UnixPrintServiceLookup.isAIX()) { + } else if (PrintServiceLookupProvider.isAIX()) { return getQueuedJobCountAIX(); } else { return new QueuedJobCount(0); @@ -468,9 +468,9 @@ } private PrintServiceAttributeSet getDynamicAttributes() { - if (UnixPrintServiceLookup.isSysV()) { + if (PrintServiceLookupProvider.isSysV()) { return getSysVServiceAttributes(); - } else if (UnixPrintServiceLookup.isAIX()) { + } else if (PrintServiceLookupProvider.isAIX()) { return getAIXServiceAttributes(); } else { return getBSDServiceAttributes();
--- a/jdk/src/java.desktop/unix/classes/sun/print/UnixPrintServiceLookup.java Thu Oct 30 08:34:51 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,964 +0,0 @@ -/* - * Copyright (c) 2000, 2014, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.print; - -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Vector; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import javax.print.DocFlavor; -import javax.print.MultiDocPrintService; -import javax.print.PrintService; -import javax.print.PrintServiceLookup; -import javax.print.attribute.Attribute; -import javax.print.attribute.AttributeSet; -import javax.print.attribute.HashPrintRequestAttributeSet; -import javax.print.attribute.HashPrintServiceAttributeSet; -import javax.print.attribute.PrintRequestAttribute; -import javax.print.attribute.PrintRequestAttributeSet; -import javax.print.attribute.PrintServiceAttribute; -import javax.print.attribute.PrintServiceAttributeSet; -import javax.print.attribute.standard.PrinterName; -import javax.print.attribute.standard.PrinterURI; -import java.io.File; -import java.io.FileReader; -import java.net.URL; -import java.nio.file.Files; - -/* - * Remind: This class uses solaris commands. We also need a linux - * version - */ -public class UnixPrintServiceLookup extends PrintServiceLookup - implements BackgroundServiceLookup, Runnable { - - /* Remind: the current implementation is static, as its assumed - * its preferable to minimize creation of PrintService instances. - * Later we should add logic to add/remove services on the fly which - * will take a hit of needing to regather the list of services. - */ - private String defaultPrinter; - private PrintService defaultPrintService; - private PrintService[] printServices; /* includes the default printer */ - private Vector<BackgroundLookupListener> lookupListeners = null; - private static String debugPrefix = "UnixPrintServiceLookup>> "; - private static boolean pollServices = true; - private static final int DEFAULT_MINREFRESH = 120; // 2 minutes - private static int minRefreshTime = DEFAULT_MINREFRESH; - - - static String osname; - - // List of commands used to deal with the printer queues on AIX - String[] lpNameComAix = { - "/usr/bin/lsallq", - "/usr/bin/lpstat -W -p|/usr/bin/expand|/usr/bin/cut -f1 -d' '", - "/usr/bin/lpstat -W -d|/usr/bin/expand|/usr/bin/cut -f1 -d' '", - "/usr/bin/lpstat -W -v" - }; - private static final int aix_lsallq = 0; - private static final int aix_lpstat_p = 1; - private static final int aix_lpstat_d = 2; - private static final int aix_lpstat_v = 3; - private static int aix_defaultPrinterEnumeration = aix_lsallq; - - static { - /* The system property "sun.java2d.print.polling" - * can be used to force the printing code to poll or not poll - * for PrintServices. - */ - String pollStr = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.java2d.print.polling")); - - if (pollStr != null) { - if (pollStr.equalsIgnoreCase("true")) { - pollServices = true; - } else if (pollStr.equalsIgnoreCase("false")) { - pollServices = false; - } - } - - /* The system property "sun.java2d.print.minRefreshTime" - * can be used to specify minimum refresh time (in seconds) - * for polling PrintServices. The default is 120. - */ - String refreshTimeStr = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction( - "sun.java2d.print.minRefreshTime")); - - if (refreshTimeStr != null) { - try { - minRefreshTime = (new Integer(refreshTimeStr)).intValue(); - } catch (NumberFormatException e) { - } - if (minRefreshTime < DEFAULT_MINREFRESH) { - minRefreshTime = DEFAULT_MINREFRESH; - } - } - - osname = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("os.name")); - - /* The system property "sun.java2d.print.aix.lpstat" - * can be used to force the usage of 'lpstat -p' to enumerate all - * printer queues. By default we use 'lsallq', because 'lpstat -p' can - * take lots of time if thousands of printers are attached to a server. - */ - if (isAIX()) { - String aixPrinterEnumerator = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.java2d.print.aix.lpstat")); - - if (aixPrinterEnumerator != null) { - if (aixPrinterEnumerator.equalsIgnoreCase("lpstat")) { - aix_defaultPrinterEnumeration = aix_lpstat_p; - } else if (aixPrinterEnumerator.equalsIgnoreCase("lsallq")) { - aix_defaultPrinterEnumeration = aix_lsallq; - } - } - } - } - - static boolean isMac() { - return osname.startsWith("Mac"); - } - - static boolean isSysV() { - return osname.equals("SunOS"); - } - - static boolean isLinux() { - return (osname.equals("Linux")); - } - - static boolean isBSD() { - return (osname.equals("Linux") || - osname.contains("OS X")); - } - - static boolean isAIX() { - return osname.equals("AIX"); - } - - static final int UNINITIALIZED = -1; - static final int BSD_LPD = 0; - static final int BSD_LPD_NG = 1; - - static int cmdIndex = UNINITIALIZED; - - String[] lpcFirstCom = { - "/usr/sbin/lpc status | grep : | sed -ne '1,1 s/://p'", - "/usr/sbin/lpc status | grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}'" - }; - - String[] lpcAllCom = { - "/usr/sbin/lpc status all | grep : | sed -e 's/://'", - "/usr/sbin/lpc status all | grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}' | sort" - }; - - String[] lpcNameCom = { - "| grep : | sed -ne 's/://p'", - "| grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}'" - }; - - - static int getBSDCommandIndex() { - String command = "/usr/sbin/lpc status all"; - String[] names = execCmd(command); - - if ((names == null) || (names.length == 0)) { - return BSD_LPD_NG; - } - - for (int i=0; i<names.length; i++) { - if (names[i].indexOf('@') != -1) { - return BSD_LPD_NG; - } - } - - return BSD_LPD; - } - - - public UnixPrintServiceLookup() { - // start the printer listener thread - if (pollServices) { - PrinterChangeListener thr = new PrinterChangeListener(); - thr.setDaemon(true); - thr.start(); - IPPPrintService.debug_println(debugPrefix+"polling turned on"); - } - } - - /* Want the PrintService which is default print service to have - * equality of reference with the equivalent in list of print services - * This isn't required by the API and there's a risk doing this will - * lead people to assume its guaranteed. - */ - public synchronized PrintService[] getPrintServices() { - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkPrintJobAccess(); - } - - if (printServices == null || !pollServices) { - refreshServices(); - } - if (printServices == null) { - return new PrintService[0]; - } else { - return printServices.clone(); - } - } - - private int addPrintServiceToList(ArrayList<PrintService> printerList, PrintService ps) { - int index = printerList.indexOf(ps); - // Check if PrintService with same name is already in the list. - if (CUPSPrinter.isCupsRunning() && index != -1) { - // Bug in Linux: Duplicate entry of a remote printer - // and treats it as local printer but it is returning wrong - // information when queried using IPP. Workaround is to remove it. - // Even CUPS ignores these entries as shown in lpstat or using - // their web configuration. - PrinterURI uri = ps.getAttribute(PrinterURI.class); - if (uri.getURI().getHost().equals("localhost")) { - IPPPrintService.debug_println(debugPrefix+"duplicate PrintService, ignoring the new local printer: "+ps); - return index; // Do not add this. - } - PrintService oldPS = printerList.get(index); - uri = oldPS.getAttribute(PrinterURI.class); - if (uri.getURI().getHost().equals("localhost")) { - IPPPrintService.debug_println(debugPrefix+"duplicate PrintService, removing existing local printer: "+oldPS); - printerList.remove(oldPS); - } else { - return index; - } - } - printerList.add(ps); - return (printerList.size() - 1); - } - - - // refreshes "printServices" - public synchronized void refreshServices() { - /* excludes the default printer */ - String[] printers = null; // array of printer names - String[] printerURIs = null; //array of printer URIs - - try { - getDefaultPrintService(); - } catch (Throwable t) { - IPPPrintService.debug_println(debugPrefix+ - "Exception getting default printer : " + t); - } - if (CUPSPrinter.isCupsRunning()) { - try { - printerURIs = CUPSPrinter.getAllPrinters(); - IPPPrintService.debug_println("CUPS URIs = " + printerURIs); - if (printerURIs != null) { - for (int p = 0; p < printerURIs.length; p++) { - IPPPrintService.debug_println("URI="+printerURIs[p]); - } - } - } catch (Throwable t) { - IPPPrintService.debug_println(debugPrefix+ - "Exception getting all CUPS printers : " + t); - } - if ((printerURIs != null) && (printerURIs.length > 0)) { - printers = new String[printerURIs.length]; - for (int i=0; i<printerURIs.length; i++) { - int lastIndex = printerURIs[i].lastIndexOf("/"); - printers[i] = printerURIs[i].substring(lastIndex+1); - } - } - } else { - if (isMac() || isSysV()) { - printers = getAllPrinterNamesSysV(); - } else if (isAIX()) { - printers = getAllPrinterNamesAIX(); - } else { //BSD - printers = getAllPrinterNamesBSD(); - } - } - - if (printers == null) { - if (defaultPrintService != null) { - printServices = new PrintService[1]; - printServices[0] = defaultPrintService; - } else { - printServices = null; - } - return; - } - - ArrayList<PrintService> printerList = new ArrayList<>(); - int defaultIndex = -1; - for (int p=0; p<printers.length; p++) { - if (printers[p] == null) { - continue; - } - if ((defaultPrintService != null) - && printers[p].equals(getPrinterDestName(defaultPrintService))) { - defaultIndex = addPrintServiceToList(printerList, defaultPrintService); - } else { - if (printServices == null) { - IPPPrintService.debug_println(debugPrefix+ - "total# of printers = "+printers.length); - - if (CUPSPrinter.isCupsRunning()) { - try { - addPrintServiceToList(printerList, - new IPPPrintService(printers[p], - printerURIs[p], - true)); - } catch (Exception e) { - IPPPrintService.debug_println(debugPrefix+ - " getAllPrinters Exception "+ - e); - - } - } else { - printerList.add(new UnixPrintService(printers[p])); - } - } else { - int j; - for (j=0; j<printServices.length; j++) { - if (printServices[j] != null) { - if (printers[p].equals(getPrinterDestName(printServices[j]))) { - printerList.add(printServices[j]); - printServices[j] = null; - break; - } - } - } - - if (j == printServices.length) { // not found? - if (CUPSPrinter.isCupsRunning()) { - try { - addPrintServiceToList(printerList, - new IPPPrintService(printers[p], - printerURIs[p], - true)); - } catch (Exception e) { - IPPPrintService.debug_println(debugPrefix+ - " getAllPrinters Exception "+ - e); - - } - } else { - printerList.add(new UnixPrintService(printers[p])); - } - } - } - } - } - - // Look for deleted services and invalidate these - if (printServices != null) { - for (int j=0; j < printServices.length; j++) { - if ((printServices[j] instanceof UnixPrintService) && - (!printServices[j].equals(defaultPrintService))) { - ((UnixPrintService)printServices[j]).invalidateService(); - } - } - } - - //if defaultService is not found in printerList - if (defaultIndex == -1 && defaultPrintService != null) { - defaultIndex = addPrintServiceToList(printerList, defaultPrintService); - } - - printServices = printerList.toArray(new PrintService[] {}); - - // swap default with the first in the list - if (defaultIndex > 0) { - PrintService saveService = printServices[0]; - printServices[0] = printServices[defaultIndex]; - printServices[defaultIndex] = saveService; - } - } - - private boolean matchesAttributes(PrintService service, - PrintServiceAttributeSet attributes) { - - Attribute [] attrs = attributes.toArray(); - for (int i=0; i<attrs.length; i++) { - @SuppressWarnings("unchecked") - Attribute serviceAttr - = service.getAttribute((Class<PrintServiceAttribute>)attrs[i].getCategory()); - if (serviceAttr == null || !serviceAttr.equals(attrs[i])) { - return false; - } - } - return true; - } - - /* This checks for validity of the printer name before passing as - * parameter to a shell command. - */ - private boolean checkPrinterName(String s) { - char c; - - for (int i=0; i < s.length(); i++) { - c = s.charAt(i); - if (Character.isLetterOrDigit(c) || - c == '-' || c == '_' || c == '.' || c == '/') { - continue; - } else { - return false; - } - } - return true; - } - - /* - * Gets the printer name compatible with the list of printers returned by - * the system when we query default or all the available printers. - */ - private String getPrinterDestName(PrintService ps) { - if (isMac()) { - return ((IPPPrintService)ps).getDest(); - } - return ps.getName(); - } - - /* On a network with many (hundreds) of network printers, it - * can save several seconds if you know all you want is a particular - * printer, to ask for that printer rather than retrieving all printers. - */ - private PrintService getServiceByName(PrinterName nameAttr) { - String name = nameAttr.getValue(); - if (name == null || name.equals("") || !checkPrinterName(name)) { - return null; - } - /* check if all printers are already available */ - if (printServices != null) { - for (PrintService printService : printServices) { - PrinterName printerName = printService.getAttribute(PrinterName.class); - if (printerName.getValue().equals(name)) { - return printService; - } - } - } - /* take CUPS into account first */ - if (CUPSPrinter.isCupsRunning()) { - try { - return new IPPPrintService(name, - new URL("http://"+ - CUPSPrinter.getServer()+":"+ - CUPSPrinter.getPort()+"/"+ - name)); - } catch (Exception e) { - IPPPrintService.debug_println(debugPrefix+ - " getServiceByName Exception "+ - e); - } - } - /* fallback if nothing not having a printer at this point */ - PrintService printer = null; - if (isMac() || isSysV()) { - printer = getNamedPrinterNameSysV(name); - } else if (isAIX()) { - printer = getNamedPrinterNameAIX(name); - } else { - printer = getNamedPrinterNameBSD(name); - } - return printer; - } - - private PrintService[] - getPrintServices(PrintServiceAttributeSet serviceSet) { - - if (serviceSet == null || serviceSet.isEmpty()) { - return getPrintServices(); - } - - /* Typically expect that if a service attribute is specified that - * its a printer name and there ought to be only one match. - * Directly retrieve that service and confirm - * that it meets the other requirements. - * If printer name isn't mentioned then go a slow path checking - * all printers if they meet the reqiremements. - */ - PrintService[] services; - PrinterName name = (PrinterName)serviceSet.get(PrinterName.class); - PrintService defService; - if (name != null && (defService = getDefaultPrintService()) != null) { - /* To avoid execing a unix command see if the client is asking - * for the default printer by name, since we already have that - * initialised. - */ - - PrinterName defName = defService.getAttribute(PrinterName.class); - - if (defName != null && name.equals(defName)) { - if (matchesAttributes(defService, serviceSet)) { - services = new PrintService[1]; - services[0] = defService; - return services; - } else { - return new PrintService[0]; - } - } else { - /* Its not the default service */ - PrintService service = getServiceByName(name); - if (service != null && - matchesAttributes(service, serviceSet)) { - services = new PrintService[1]; - services[0] = service; - return services; - } else { - return new PrintService[0]; - } - } - } else { - /* specified service attributes don't include a name.*/ - Vector<PrintService> matchedServices = new Vector<>(); - services = getPrintServices(); - for (int i = 0; i< services.length; i++) { - if (matchesAttributes(services[i], serviceSet)) { - matchedServices.add(services[i]); - } - } - services = new PrintService[matchedServices.size()]; - for (int i = 0; i< services.length; i++) { - services[i] = matchedServices.elementAt(i); - } - return services; - } - } - - /* - * If service attributes are specified then there must be additional - * filtering. - */ - public PrintService[] getPrintServices(DocFlavor flavor, - AttributeSet attributes) { - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkPrintJobAccess(); - } - PrintRequestAttributeSet requestSet = null; - PrintServiceAttributeSet serviceSet = null; - - if (attributes != null && !attributes.isEmpty()) { - - requestSet = new HashPrintRequestAttributeSet(); - serviceSet = new HashPrintServiceAttributeSet(); - - Attribute[] attrs = attributes.toArray(); - for (int i=0; i<attrs.length; i++) { - if (attrs[i] instanceof PrintRequestAttribute) { - requestSet.add(attrs[i]); - } else if (attrs[i] instanceof PrintServiceAttribute) { - serviceSet.add(attrs[i]); - } - } - } - - PrintService[] services = getPrintServices(serviceSet); - if (services.length == 0) { - return services; - } - - if (CUPSPrinter.isCupsRunning()) { - ArrayList<PrintService> matchingServices = new ArrayList<>(); - for (int i=0; i<services.length; i++) { - try { - if (services[i]. - getUnsupportedAttributes(flavor, requestSet) == null) { - matchingServices.add(services[i]); - } - } catch (IllegalArgumentException e) { - } - } - services = new PrintService[matchingServices.size()]; - return matchingServices.toArray(services); - - } else { - // We only need to compare 1 PrintService because all - // UnixPrintServices are the same anyway. We will not use - // default PrintService because it might be null. - PrintService service = services[0]; - if ((flavor == null || - service.isDocFlavorSupported(flavor)) && - service.getUnsupportedAttributes(flavor, requestSet) == null) - { - return services; - } else { - return new PrintService[0]; - } - } - } - - /* - * return empty array as don't support multi docs - */ - public MultiDocPrintService[] - getMultiDocPrintServices(DocFlavor[] flavors, - AttributeSet attributes) { - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkPrintJobAccess(); - } - return new MultiDocPrintService[0]; - } - - - public synchronized PrintService getDefaultPrintService() { - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkPrintJobAccess(); - } - - // clear defaultPrintService - defaultPrintService = null; - String psuri = null; - - IPPPrintService.debug_println("isRunning ? "+ - (CUPSPrinter.isCupsRunning())); - if (CUPSPrinter.isCupsRunning()) { - String[] printerInfo = CUPSPrinter.getDefaultPrinter(); - if (printerInfo != null && printerInfo.length >= 2) { - defaultPrinter = printerInfo[0]; - psuri = printerInfo[1]; - } - } else { - if (isMac() || isSysV()) { - defaultPrinter = getDefaultPrinterNameSysV(); - } else if (isAIX()) { - defaultPrinter = getDefaultPrinterNameAIX(); - } else { - defaultPrinter = getDefaultPrinterNameBSD(); - } - } - if (defaultPrinter == null) { - return null; - } - defaultPrintService = null; - if (printServices != null) { - for (int j=0; j<printServices.length; j++) { - if (defaultPrinter.equals(getPrinterDestName(printServices[j]))) { - defaultPrintService = printServices[j]; - break; - } - } - } - if (defaultPrintService == null) { - if (CUPSPrinter.isCupsRunning()) { - try { - PrintService defaultPS; - if ((psuri != null) && !psuri.startsWith("file")) { - defaultPS = new IPPPrintService(defaultPrinter, - psuri, true); - } else { - defaultPS = new IPPPrintService(defaultPrinter, - new URL("http://"+ - CUPSPrinter.getServer()+":"+ - CUPSPrinter.getPort()+"/"+ - defaultPrinter)); - } - defaultPrintService = defaultPS; - } catch (Exception e) { - } - } else { - defaultPrintService = new UnixPrintService(defaultPrinter); - } - } - - return defaultPrintService; - } - - public synchronized void - getServicesInbackground(BackgroundLookupListener listener) { - if (printServices != null) { - listener.notifyServices(printServices); - } else { - if (lookupListeners == null) { - lookupListeners = new Vector<>(); - lookupListeners.add(listener); - Thread lookupThread = new Thread(this); - lookupThread.start(); - } else { - lookupListeners.add(listener); - } - } - } - - /* This method isn't used in most cases because we rely on code in - * javax.print.PrintServiceLookup. This is needed just for the cases - * where those interfaces are by-passed. - */ - private PrintService[] copyOf(PrintService[] inArr) { - if (inArr == null || inArr.length == 0) { - return inArr; - } else { - PrintService []outArr = new PrintService[inArr.length]; - System.arraycopy(inArr, 0, outArr, 0, inArr.length); - return outArr; - } - } - - public void run() { - PrintService[] services = getPrintServices(); - synchronized (this) { - BackgroundLookupListener listener; - for (int i=0; i<lookupListeners.size(); i++) { - listener = lookupListeners.elementAt(i); - listener.notifyServices(copyOf(services)); - } - lookupListeners = null; - } - } - - private String getDefaultPrinterNameBSD() { - if (cmdIndex == UNINITIALIZED) { - cmdIndex = getBSDCommandIndex(); - } - String[] names = execCmd(lpcFirstCom[cmdIndex]); - if (names == null || names.length == 0) { - return null; - } - - if ((cmdIndex==BSD_LPD_NG) && - (names[0].startsWith("missingprinter"))) { - return null; - } - return names[0]; - } - - private PrintService getNamedPrinterNameBSD(String name) { - if (cmdIndex == UNINITIALIZED) { - cmdIndex = getBSDCommandIndex(); - } - String command = "/usr/sbin/lpc status " + name + lpcNameCom[cmdIndex]; - String[] result = execCmd(command); - - if (result == null || !(result[0].equals(name))) { - return null; - } - return new UnixPrintService(name); - } - - private String[] getAllPrinterNamesBSD() { - if (cmdIndex == UNINITIALIZED) { - cmdIndex = getBSDCommandIndex(); - } - String[] names = execCmd(lpcAllCom[cmdIndex]); - if (names == null || names.length == 0) { - return null; - } - return names; - } - - static String getDefaultPrinterNameSysV() { - String defaultPrinter = "lp"; - String command = "/usr/bin/lpstat -d"; - - String [] names = execCmd(command); - if (names == null || names.length == 0) { - return defaultPrinter; - } else { - int index = names[0].indexOf(":"); - if (index == -1 || (names[0].length() <= index+1)) { - return null; - } else { - String name = names[0].substring(index+1).trim(); - if (name.length() == 0) { - return null; - } else { - return name; - } - } - } - } - - private PrintService getNamedPrinterNameSysV(String name) { - - String command = "/usr/bin/lpstat -v " + name; - String []result = execCmd(command); - - if (result == null || result[0].indexOf("unknown printer") > 0) { - return null; - } else { - return new UnixPrintService(name); - } - } - - private String[] getAllPrinterNamesSysV() { - String defaultPrinter = "lp"; - String command = "/usr/bin/lpstat -v|/usr/bin/expand|/usr/bin/cut -f3 -d' ' |/usr/bin/cut -f1 -d':' | /usr/bin/sort"; - - String [] names = execCmd(command); - ArrayList<String> printerNames = new ArrayList<>(); - for (int i=0; i < names.length; i++) { - if (!names[i].equals("_default") && - !names[i].equals(defaultPrinter) && - !names[i].equals("")) { - printerNames.add(names[i]); - } - } - return printerNames.toArray(new String[printerNames.size()]); - } - - private String getDefaultPrinterNameAIX() { - String[] names = execCmd(lpNameComAix[aix_lpstat_d]); - // Remove headers and bogus entries added by remote printers. - names = UnixPrintService.filterPrinterNamesAIX(names); - if (names == null || names.length != 1) { - // No default printer found - return null; - } else { - return names[0]; - } - } - - private PrintService getNamedPrinterNameAIX(String name) { - // On AIX there should be no blank after '-v'. - String[] result = execCmd(lpNameComAix[aix_lpstat_v] + name); - // Remove headers and bogus entries added by remote printers. - result = UnixPrintService.filterPrinterNamesAIX(result); - if (result == null || result.length != 1) { - return null; - } else { - return new UnixPrintService(name); - } - } - - private String[] getAllPrinterNamesAIX() { - // Determine all printers of the system. - String [] names = execCmd(lpNameComAix[aix_defaultPrinterEnumeration]); - - // Remove headers and bogus entries added by remote printers. - names = UnixPrintService.filterPrinterNamesAIX(names); - - ArrayList<String> printerNames = new ArrayList<String>(); - for ( int i=0; i < names.length; i++) { - printerNames.add(names[i]); - } - return printerNames.toArray(new String[printerNames.size()]); - } - - static String[] execCmd(final String command) { - ArrayList<String> results = null; - try { - final String[] cmd = new String[3]; - if (isSysV() || isAIX()) { - cmd[0] = "/usr/bin/sh"; - cmd[1] = "-c"; - cmd[2] = "env LC_ALL=C " + command; - } else { - cmd[0] = "/bin/sh"; - cmd[1] = "-c"; - cmd[2] = "LC_ALL=C " + command; - } - - results = AccessController.doPrivileged( - new PrivilegedExceptionAction<ArrayList<String>>() { - public ArrayList<String> run() throws IOException { - - Process proc; - BufferedReader bufferedReader = null; - File f = Files.createTempFile("prn","xc").toFile(); - cmd[2] = cmd[2]+">"+f.getAbsolutePath(); - - proc = Runtime.getRuntime().exec(cmd); - try { - boolean done = false; // in case of interrupt. - while (!done) { - try { - proc.waitFor(); - done = true; - } catch (InterruptedException e) { - } - } - - if (proc.exitValue() == 0) { - FileReader reader = new FileReader(f); - bufferedReader = new BufferedReader(reader); - String line; - ArrayList<String> results = new ArrayList<>(); - while ((line = bufferedReader.readLine()) - != null) { - results.add(line); - } - return results; - } - } finally { - f.delete(); - // promptly close all streams. - if (bufferedReader != null) { - bufferedReader.close(); - } - proc.getInputStream().close(); - proc.getErrorStream().close(); - proc.getOutputStream().close(); - } - return null; - } - }); - } catch (PrivilegedActionException e) { - } - if (results == null) { - return new String[0]; - } else { - return results.toArray(new String[results.size()]); - } - } - - private class PrinterChangeListener extends Thread { - - public void run() { - int refreshSecs; - while (true) { - try { - refreshServices(); - } catch (Exception se) { - IPPPrintService.debug_println(debugPrefix+"Exception in refresh thread."); - break; - } - - if ((printServices != null) && - (printServices.length > minRefreshTime)) { - // compute new refresh time 1 printer = 1 sec - refreshSecs = printServices.length; - } else { - refreshSecs = minRefreshTime; - } - try { - sleep(refreshSecs * 1000); - } catch (InterruptedException e) { - break; - } - } - } - } -}
--- a/jdk/src/java.desktop/unix/native/common/java2d/opengl/GLXGraphicsConfig.c Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/unix/native/common/java2d/opengl/GLXGraphicsConfig.c Wed Jul 05 20:05:54 2017 +0200 @@ -398,8 +398,8 @@ static GLXPbuffer GLXGC_InitScratchPbuffer(GLXFBConfig fbconfig) { - int pbattrlist[] = {GLX_PBUFFER_WIDTH, 1, - GLX_PBUFFER_HEIGHT, 1, + int pbattrlist[] = {GLX_PBUFFER_WIDTH, 4, + GLX_PBUFFER_HEIGHT, 4, GLX_PRESERVED_CONTENTS, GL_FALSE, 0};
--- a/jdk/src/java.desktop/windows/classes/META-INF/services/javax.print.PrintServiceLookup Thu Oct 30 08:34:51 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -# Provider for Java Print Service -sun.print.Win32PrintServiceLookup
--- a/jdk/src/java.desktop/windows/classes/META-INF/services/javax.print.StreamPrintServiceFactory Thu Oct 30 08:34:51 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -# Providers for Java 2D/JPS Stream print services. -sun.print.PSStreamPrinterFactory
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java Wed Jul 05 20:05:54 2017 +0200 @@ -1400,7 +1400,9 @@ * The saved device transform is needed as the current transform * is not likely to be the same. */ - deviceClip(savedClip.getPathIterator(savedTransform)); + if (savedClip != null) { + deviceClip(savedClip.getPathIterator(savedTransform)); + } /* Scale the bounding rectangle by the scale transform. * Because the scaling transform has only x and y
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java Thu Oct 30 08:34:51 2014 -0700 +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java Wed Jul 05 20:05:54 2017 +0200 @@ -93,7 +93,7 @@ import sun.print.SunPageSelection; import sun.print.Win32MediaTray; import sun.print.Win32PrintService; -import sun.print.Win32PrintServiceLookup; +import sun.print.PrintServiceLookupProvider; import sun.print.ServiceDialog; import sun.print.DialogOwner; @@ -454,7 +454,7 @@ // native printer is different ! // we update the current PrintService try { - setPrintService(Win32PrintServiceLookup. + setPrintService(PrintServiceLookupProvider. getWin32PrintLUS(). getPrintServiceByName(printerName)); } catch (PrinterException e) { @@ -628,7 +628,7 @@ String printerName = getNativePrintService(); if (printerName != null) { - myService = Win32PrintServiceLookup.getWin32PrintLUS(). + myService = PrintServiceLookupProvider.getWin32PrintLUS(). getPrintServiceByName(printerName); // no need to call setNativePrintService as this name is // currently set in native
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java Wed Jul 05 20:05:54 2017 +0200 @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2000, 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.print; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.IOException; +import java.util.ArrayList; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import javax.print.DocFlavor; +import javax.print.MultiDocPrintService; +import javax.print.PrintService; +import javax.print.PrintServiceLookup; +import javax.print.attribute.Attribute; +import javax.print.attribute.AttributeSet; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.HashPrintServiceAttributeSet; +import javax.print.attribute.PrintRequestAttribute; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.PrintServiceAttribute; +import javax.print.attribute.PrintServiceAttributeSet; +import javax.print.attribute.standar