This commit is contained in:
Andrew Haley 2018-10-01 09:56:45 +01:00
commit 08e1f72237
268 changed files with 6381 additions and 4817 deletions

View File

@ -513,3 +513,4 @@ ef57958c7c511162da8d9a75f0b977f0f7ac464e jdk-12+7
8f594f75e0547d4ca16649cb3501659e3155e81b jdk-12+10
f0f5d23449d31f1b3580c8a73313918cafeaefd7 jdk-12+11
15094d12a632f452a2064318a4e416d0c7a9ce0c jdk-12+12
511a9946f83e3e3c7b9dbe1840367063fb39b4e1 jdk-12+13

View File

@ -351,6 +351,11 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES],
AC_MSG_RESULT([no])
fi
# Disable unsupported GCs for Zero
if HOTSPOT_CHECK_JVM_VARIANT(zero); then
DISABLED_JVM_FEATURES="$DISABLED_JVM_FEATURES epsilongc g1gc zgc"
fi
# Turn on additional features based on other parts of configure
if test "x$INCLUDE_DTRACE" = "xtrue"; then
JVM_FEATURES="$JVM_FEATURES dtrace"

View File

@ -840,7 +840,7 @@ var getJibProfilesDependencies = function (input, common) {
linux_x64: "gcc7.3.0-OEL6.4+1.0",
macosx_x64: "Xcode9.4-MacOSX10.13+1.0",
solaris_x64: "SS12u4-Solaris11u1+1.0",
solaris_sparcv9: "SS12u4-Solaris11u1+1.1",
solaris_sparcv9: "SS12u6-Solaris11u3+1.0",
windows_x64: "VS2017-15.5.5+1.0",
linux_aarch64: (input.profile != null && input.profile.indexOf("arm64") >= 0
? "gcc-linaro-aarch64-linux-gnu-4.8-2013.11_linux+1.0"

View File

@ -34,18 +34,19 @@
# install in a separate temporary image.
#
# The Solaris Studio installation must contain at least these packages:
# developer/developerstudio-126/backend 12.6-1.0.0.0 i--
# developer/developerstudio-126/c++ 12.6-1.0.0.0 i--
# developer/developerstudio-126/cc 12.6-1.0.0.0 i--
# developer/developerstudio-126/dbx (solarisstudio) 12.6-1.0.0.0 i--
# developer/developerstudio-126/library/c++-libs 12.6-1.0.0.0 i--
# developer/developerstudio-126/library/math-libs 12.6-1.0.0.0 i--
# developer/developerstudio-126/library/c-libs 12.6-1.0.0.0 i--
# developer/developerstudio-126/library/studio-gccrt 12.6-1.0.0.0 i--
# developer/developerstudio-126/studio-common 12.6-1.0.0.0 i--
# developer/developerstudio-126/studio-ja 12.6-1.0.0.0 i--
# developer/developerstudio-126/studio-legal 12.6-1.0.0.0 i--
# developer/developerstudio-126/studio-zhCN 12.6-1.0.0.0 i--
#developer/developerstudio-126/backend 12.6-1.0.0.1
#developer/developerstudio-126/c++ 12.6-1.0.2.0
#developer/developerstudio-126/cc 12.6-1.0.1.0
#developer/developerstudio-126/dbx 12.6-1.0.0.1
#developer/developerstudio-126/library/c++-libs 12.6-1.0.2.0
#developer/developerstudio-126/library/c-libs 12.6-1.0.0.1
#developer/developerstudio-126/library/f90-libs 12.6-1.0.0.1
#developer/developerstudio-126/library/math-libs 12.6-1.0.0.1
#developer/developerstudio-126/library/studio-gccrt 12.6-1.0.0.1
#developer/developerstudio-126/studio-common 12.6-1.0.0.1
#developer/developerstudio-126/studio-ja 12.6-1.0.0.1
#developer/developerstudio-126/studio-legal 12.6-1.0.0.1
#developer/developerstudio-126/studio-zhCN 12.6-1.0.0.1
#
# erik.joelsson@oracle.com
@ -93,7 +94,7 @@ if [ ! -d $INSTALL_ROOT ]; then
pkg -R $INSTALL_ROOT set-publisher -P -g ${PUBLISHER_URI} solaris
sudo pkg -R $INSTALL_ROOT install --accept entire@$SOLARIS_ENTIRE_VERSION \
system/install developer/gnu-binutils system/library/mmheap system/picl \
developer/assembler
developer/assembler system/library/freetype-2
else
echo "Skipping installing packages"
fi

View File

@ -244,7 +244,7 @@ ifeq ($(OPENJDK_TARGET_OS), aix)
EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
OPTIMIZATION := HIGH, \
CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS_JDKLIB) $(LIBJLI_CFLAGS) \
CFLAGS := $(STATIC_LIBRARY_FLAGS) $(CFLAGS_JDKLIB) $(LIBJLI_CFLAGS) \
$(addprefix -I, $(LIBJLI_SRC_DIRS)), \
ARFLAGS := $(ARFLAGS), \
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static))

View File

@ -1,3 +1,34 @@
/*
*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package java2d;
import java.awt.Color;

View File

@ -1,3 +1,34 @@
/*
*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package java2d;
import java.awt.Color;

View File

@ -870,8 +870,8 @@ void LIRGenerator::do_ArithmeticOp(ArithmeticOp* x) {
case doubleTag: do_ArithmeticOp_FPU(x); return;
case longTag: do_ArithmeticOp_Long(x); return;
case intTag: do_ArithmeticOp_Int(x); return;
default: ShouldNotReachHere(); return;
}
ShouldNotReachHere();
}

View File

@ -2996,6 +2996,7 @@ void TemplateTable::resolve_cache_and_index(int byte_no,
switch (code) {
case Bytecodes::_nofast_getfield: code = Bytecodes::_getfield; break;
case Bytecodes::_nofast_putfield: code = Bytecodes::_putfield; break;
default: break;
}
assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");

View File

@ -2403,8 +2403,9 @@ void LIR_Assembler::intrinsic_op(LIR_Code code, LIR_Opr value, LIR_Opr tmp, LIR_
if (UseAVX > 2 && !VM_Version::supports_avx512vl()) {
assert(tmp->is_valid(), "need temporary");
__ vpandn(dest->as_xmm_double_reg(), tmp->as_xmm_double_reg(), value->as_xmm_double_reg(), 2);
} else {
} else
#endif
{
if (dest->as_xmm_double_reg() != value->as_xmm_double_reg()) {
__ movdbl(dest->as_xmm_double_reg(), value->as_xmm_double_reg());
}

View File

@ -131,7 +131,8 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
case T_BYTE: slow_case_addr = jni_GetByteField_addr(); break;
case T_CHAR: slow_case_addr = jni_GetCharField_addr(); break;
case T_SHORT: slow_case_addr = jni_GetShortField_addr(); break;
case T_INT: slow_case_addr = jni_GetIntField_addr();
case T_INT: slow_case_addr = jni_GetIntField_addr(); break;
default: ShouldNotReachHere();
}
// tail call
__ jump (ExternalAddress(slow_case_addr));

View File

@ -87,8 +87,8 @@ class StubGenerator: public StubCodeGenerator {
case T_INT: inc_counter_np(SharedRuntime::_jint_array_copy_ctr); return;
case T_LONG: inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); return;
case T_OBJECT: inc_counter_np(SharedRuntime::_oop_array_copy_ctr); return;
default: ShouldNotReachHere();
}
ShouldNotReachHere();
#endif //PRODUCT
}

View File

@ -1877,12 +1877,16 @@ void* os::get_default_process_handle() {
return (void*)::dlopen(NULL, RTLD_LAZY);
}
static bool _print_ascii_file(const char* filename, outputStream* st) {
static bool _print_ascii_file(const char* filename, outputStream* st, const char* hdr = NULL) {
int fd = ::open(filename, O_RDONLY);
if (fd == -1) {
return false;
}
if (hdr != NULL) {
st->print_cr("%s", hdr);
}
char buf[33];
int bytes;
buf[32] = '\0';
@ -1975,6 +1979,8 @@ void os::print_os_info(outputStream* st) {
os::Linux::print_proc_sys_info(st);
os::Linux::print_ld_preload_file(st);
os::Linux::print_container_info(st);
}
@ -2133,6 +2139,11 @@ void os::Linux::print_full_memory_info(outputStream* st) {
st->cr();
}
void os::Linux::print_ld_preload_file(outputStream* st) {
_print_ascii_file("/etc/ld.so.preload", st, "\n/etc/ld.so.preload:");
st->cr();
}
void os::Linux::print_container_info(outputStream* st) {
if (!OSContainer::is_containerized()) {
return;

View File

@ -114,6 +114,7 @@ class Linux {
static void print_distro_info(outputStream* st);
static void print_libversion_info(outputStream* st);
static void print_proc_sys_info(outputStream* st);
static void print_ld_preload_file(outputStream* st);
public:
static bool _stack_is_executable;

View File

@ -47,11 +47,10 @@
// the singleton class the_null_class_loader_data().
#include "precompiled.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderDataGraph.inline.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/metadataOnStackMark.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/packageEntry.hpp"
#include "classfile/symbolTable.hpp"
@ -60,9 +59,7 @@
#include "logging/logStream.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceShared.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/access.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/oopHandle.inline.hpp"
@ -72,14 +69,10 @@
#include "runtime/mutex.hpp"
#include "runtime/orderAccess.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/safepointVerifiers.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
volatile size_t ClassLoaderDataGraph::_num_array_classes = 0;
volatile size_t ClassLoaderDataGraph::_num_instance_classes = 0;
ClassLoaderData * ClassLoaderData::_the_null_class_loader_data = NULL;
void ClassLoaderData::init_null_class_loader_data() {
@ -345,6 +338,11 @@ void ClassLoaderData::loaded_classes_do(KlassClosure* klass_closure) {
for (Klass* k = OrderAccess::load_acquire(&_klasses); k != NULL; k = k->next_link()) {
// Do not filter ArrayKlass oops here...
if (k->is_array_klass() || (k->is_instance_klass() && InstanceKlass::cast(k)->is_loaded())) {
#ifdef ASSERT
oop m = k->java_mirror();
assert(m != NULL, "NULL mirror");
assert(m->is_a(SystemDictionary::Class_klass()), "invalid mirror");
#endif
klass_closure->do_klass(k);
}
}
@ -444,13 +442,6 @@ void ClassLoaderData::record_dependency(const Klass* k) {
}
}
void ClassLoaderDataGraph::clear_claimed_marks() {
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
cld->clear_claimed();
}
}
void ClassLoaderData::add_class(Klass* k, bool publicize /* true */) {
{
MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag);
@ -478,78 +469,6 @@ void ClassLoaderData::add_class(Klass* k, bool publicize /* true */) {
}
}
// Class iterator used by the compiler. It gets some number of classes at
// a safepoint to decay invocation counters on the methods.
class ClassLoaderDataGraphKlassIteratorStatic {
ClassLoaderData* _current_loader_data;
Klass* _current_class_entry;
public:
ClassLoaderDataGraphKlassIteratorStatic() : _current_loader_data(NULL), _current_class_entry(NULL) {}
InstanceKlass* try_get_next_class() {
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
size_t max_classes = ClassLoaderDataGraph::num_instance_classes();
assert(max_classes > 0, "should not be called with no instance classes");
for (size_t i = 0; i < max_classes; ) {
if (_current_class_entry != NULL) {
Klass* k = _current_class_entry;
_current_class_entry = _current_class_entry->next_link();
if (k->is_instance_klass()) {
InstanceKlass* ik = InstanceKlass::cast(k);
i++; // count all instance classes found
// Not yet loaded classes are counted in max_classes
// but only return loaded classes.
if (ik->is_loaded()) {
return ik;
}
}
} else {
// Go to next CLD
if (_current_loader_data != NULL) {
_current_loader_data = _current_loader_data->next();
}
// Start at the beginning
if (_current_loader_data == NULL) {
_current_loader_data = ClassLoaderDataGraph::_head;
}
_current_class_entry = _current_loader_data->klasses();
}
}
// Should never be reached unless all instance classes have failed or are not fully loaded.
// Caller handles NULL.
return NULL;
}
// If the current class for the static iterator is a class being unloaded or
// deallocated, adjust the current class.
void adjust_saved_class(ClassLoaderData* cld) {
if (_current_loader_data == cld) {
_current_loader_data = cld->next();
if (_current_loader_data != NULL) {
_current_class_entry = _current_loader_data->klasses();
} // else try_get_next_class will start at the head
}
}
void adjust_saved_class(Klass* klass) {
if (_current_class_entry == klass) {
_current_class_entry = klass->next_link();
}
}
};
static ClassLoaderDataGraphKlassIteratorStatic static_klass_iterator;
InstanceKlass* ClassLoaderDataGraph::try_get_next_class() {
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
return static_klass_iterator.try_get_next_class();
}
void ClassLoaderData::initialize_holder(Handle loader_or_mirror) {
if (loader_or_mirror() != NULL) {
assert(_holder.is_null(), "never replace holders");
@ -563,7 +482,7 @@ void ClassLoaderData::remove_class(Klass* scratch_class) {
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
// Adjust global class iterator.
static_klass_iterator.adjust_saved_class(scratch_class);
ClassLoaderDataGraph::adjust_saved_class(scratch_class);
Klass* prev = NULL;
for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
@ -605,12 +524,13 @@ void ClassLoaderData::unload() {
// if they are not already on the _klasses list.
free_deallocate_list_C_heap_structures();
// Tell serviceability tools these classes are unloading
// Clean up class dependencies and tell serviceability tools
// these classes are unloading. Must be called
// after erroneous classes are released.
classes_do(InstanceKlass::notify_unload_class);
classes_do(InstanceKlass::unload_class);
// Clean up global class iterator for compiler
static_klass_iterator.adjust_saved_class(this);
ClassLoaderDataGraph::adjust_saved_class(this);
}
ModuleEntryTable* ClassLoaderData::modules() {
@ -913,41 +833,6 @@ void ClassLoaderData::free_deallocate_list() {
}
}
void ClassLoaderDataGraph::clean_deallocate_lists(bool walk_previous_versions) {
assert(SafepointSynchronize::is_at_safepoint(), "must only be called at safepoint");
uint loaders_processed = 0;
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
// is_alive check will be necessary for concurrent class unloading.
if (cld->is_alive()) {
// clean metaspace
if (walk_previous_versions) {
cld->classes_do(InstanceKlass::purge_previous_versions);
}
cld->free_deallocate_list();
loaders_processed++;
}
}
log_debug(class, loader, data)("clean_deallocate_lists: loaders processed %u %s",
loaders_processed, walk_previous_versions ? "walk_previous_versions" : "");
}
void ClassLoaderDataGraph::walk_metadata_and_clean_metaspaces() {
assert(SafepointSynchronize::is_at_safepoint(), "must only be called at safepoint");
_should_clean_deallocate_lists = false; // assume everything gets cleaned
// Mark metadata seen on the stack so we can delete unreferenced entries.
// Walk all metadata, including the expensive code cache walk, only for class redefinition.
// The MetadataOnStackMark walk during redefinition saves previous versions if it finds old methods
// on the stack or in the code cache, so we only have to repeat the full walk if
// they were found at that time.
// TODO: have redefinition clean old methods out of the code cache. They still exist in some places.
bool walk_all_metadata = InstanceKlass::has_previous_versions_and_reset();
MetadataOnStackMark md_on_stack(walk_all_metadata);
clean_deallocate_lists(walk_all_metadata);
}
// This is distinct from free_deallocate_list. For class loader data that are
// unloading, this frees the C heap memory for items on the list, and unlinks
// scratch or error classes so that unloading events aren't triggered for these
@ -1069,523 +954,3 @@ bool ClassLoaderData::contains_klass(Klass* klass) {
}
return false;
}
// GC root of class loader data created.
ClassLoaderData* ClassLoaderDataGraph::_head = NULL;
ClassLoaderData* ClassLoaderDataGraph::_unloading = NULL;
ClassLoaderData* ClassLoaderDataGraph::_saved_unloading = NULL;
ClassLoaderData* ClassLoaderDataGraph::_saved_head = NULL;
bool ClassLoaderDataGraph::_should_purge = false;
bool ClassLoaderDataGraph::_should_clean_deallocate_lists = false;
bool ClassLoaderDataGraph::_safepoint_cleanup_needed = false;
bool ClassLoaderDataGraph::_metaspace_oom = false;
// Add a new class loader data node to the list. Assign the newly created
// ClassLoaderData into the java/lang/ClassLoader object as a hidden field
ClassLoaderData* ClassLoaderDataGraph::add_to_graph(Handle loader, bool is_unsafe_anonymous) {
assert_lock_strong(ClassLoaderDataGraph_lock);
ClassLoaderData* cld;
// First check if another thread beat us to creating the CLD and installing
// it into the loader while we were waiting for the lock.
if (!is_unsafe_anonymous && loader.not_null()) {
cld = java_lang_ClassLoader::loader_data_acquire(loader());
if (cld != NULL) {
return cld;
}
}
// We mustn't GC until we've installed the ClassLoaderData in the Graph since the CLD
// contains oops in _handles that must be walked. GC doesn't walk CLD from the
// loader oop in all collections, particularly young collections.
NoSafepointVerifier no_safepoints;
cld = new ClassLoaderData(loader, is_unsafe_anonymous);
// First install the new CLD to the Graph.
cld->set_next(_head);
_head = cld;
// Next associate with the class_loader.
if (!is_unsafe_anonymous) {
// Use OrderAccess, since readers need to get the loader_data only after
// it's added to the Graph
java_lang_ClassLoader::release_set_loader_data(loader(), cld);
}
// Lastly log, if requested
LogTarget(Trace, class, loader, data) lt;
if (lt.is_enabled()) {
ResourceMark rm;
LogStream ls(lt);
ls.print("create ");
cld->print_value_on(&ls);
ls.cr();
}
return cld;
}
ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_unsafe_anonymous) {
MutexLocker ml(ClassLoaderDataGraph_lock);
ClassLoaderData* loader_data = add_to_graph(loader, is_unsafe_anonymous);
return loader_data;
}
void ClassLoaderDataGraph::cld_do(CLDClosure* cl) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->_next) {
cl->do_cld(cld);
}
}
void ClassLoaderDataGraph::cld_unloading_do(CLDClosure* cl) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
// Only walk the head until any clds not purged from prior unloading
// (CMS doesn't purge right away).
for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
assert(cld->is_unloading(), "invariant");
cl->do_cld(cld);
}
}
void ClassLoaderDataGraph::roots_cld_do(CLDClosure* strong, CLDClosure* weak) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->_next) {
CLDClosure* closure = cld->keep_alive() ? strong : weak;
if (closure != NULL) {
closure->do_cld(cld);
}
}
}
void ClassLoaderDataGraph::always_strong_cld_do(CLDClosure* cl) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
if (ClassUnloading) {
roots_cld_do(cl, NULL);
} else {
cld_do(cl);
}
}
// Closure for locking and iterating through classes.
LockedClassesDo::LockedClassesDo(classes_do_func_t f) : _function(f) {
ClassLoaderDataGraph_lock->lock();
}
LockedClassesDo::LockedClassesDo() : _function(NULL) {
// callers provide their own do_klass
ClassLoaderDataGraph_lock->lock();
}
LockedClassesDo::~LockedClassesDo() { ClassLoaderDataGraph_lock->unlock(); }
// Iterating over the CLDG needs to be locked because
// unloading can remove entries concurrently soon.
class ClassLoaderDataGraphIterator : public StackObj {
ClassLoaderData* _next;
HandleMark _hm; // clean up handles when this is done.
Handle _holder;
Thread* _thread;
void hold_next() {
if (_next != NULL) {
_holder = Handle(_thread, _next->holder_phantom());
}
}
public:
ClassLoaderDataGraphIterator() : _next(ClassLoaderDataGraph::_head) {
_thread = Thread::current();
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
hold_next();
}
bool repeat() const {
return _next != NULL;
}
ClassLoaderData* get_next() {
ClassLoaderData* next = _next;
if (_next != NULL) {
_next = _next->next();
hold_next();
}
return next;
}
};
// These functions assume that the caller has locked the ClassLoaderDataGraph_lock
// if they are not calling the function from a safepoint.
void ClassLoaderDataGraph::classes_do(KlassClosure* klass_closure) {
ClassLoaderDataGraphIterator iter;
while (iter.repeat()) {
ClassLoaderData* cld = iter.get_next();
cld->classes_do(klass_closure);
}
}
void ClassLoaderDataGraph::classes_do(void f(Klass* const)) {
ClassLoaderDataGraphIterator iter;
while (iter.repeat()) {
ClassLoaderData* cld = iter.get_next();
cld->classes_do(f);
}
}
void ClassLoaderDataGraph::methods_do(void f(Method*)) {
ClassLoaderDataGraphIterator iter;
while (iter.repeat()) {
ClassLoaderData* cld = iter.get_next();
cld->methods_do(f);
}
}
void ClassLoaderDataGraph::modules_do(void f(ModuleEntry*)) {
assert_locked_or_safepoint(Module_lock);
ClassLoaderDataGraphIterator iter;
while (iter.repeat()) {
ClassLoaderData* cld = iter.get_next();
cld->modules_do(f);
}
}
void ClassLoaderDataGraph::modules_unloading_do(void f(ModuleEntry*)) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
// Only walk the head until any clds not purged from prior unloading
// (CMS doesn't purge right away).
for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
assert(cld->is_unloading(), "invariant");
cld->modules_do(f);
}
}
void ClassLoaderDataGraph::packages_do(void f(PackageEntry*)) {
assert_locked_or_safepoint(Module_lock);
ClassLoaderDataGraphIterator iter;
while (iter.repeat()) {
ClassLoaderData* cld = iter.get_next();
cld->packages_do(f);
}
}
void ClassLoaderDataGraph::packages_unloading_do(void f(PackageEntry*)) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
// Only walk the head until any clds not purged from prior unloading
// (CMS doesn't purge right away).
for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
assert(cld->is_unloading(), "invariant");
cld->packages_do(f);
}
}
void ClassLoaderDataGraph::loaded_classes_do(KlassClosure* klass_closure) {
ClassLoaderDataGraphIterator iter;
while (iter.repeat()) {
ClassLoaderData* cld = iter.get_next();
cld->loaded_classes_do(klass_closure);
}
}
// This case can block but cannot do unloading (called from CDS)
void ClassLoaderDataGraph::unlocked_loaded_classes_do(KlassClosure* klass_closure) {
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
cld->loaded_classes_do(klass_closure);
}
}
void ClassLoaderDataGraph::classes_unloading_do(void f(Klass* const)) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
// Only walk the head until any clds not purged from prior unloading
// (CMS doesn't purge right away).
for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
assert(cld->is_unloading(), "invariant");
cld->classes_do(f);
}
}
#define FOR_ALL_DICTIONARY(X) ClassLoaderDataGraphIterator iter; \
ClassLoaderData* X; \
while ((X = iter.get_next()) != NULL) \
if (X->dictionary() != NULL)
// Walk classes in the loaded class dictionaries in various forms.
// Only walks the classes defined in this class loader.
void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*)) {
FOR_ALL_DICTIONARY(cld) {
cld->dictionary()->classes_do(f);
}
}
// Only walks the classes defined in this class loader.
void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*, TRAPS), TRAPS) {
FOR_ALL_DICTIONARY(cld) {
cld->dictionary()->classes_do(f, CHECK);
}
}
void ClassLoaderDataGraph::verify_dictionary() {
FOR_ALL_DICTIONARY(cld) {
cld->dictionary()->verify();
}
}
void ClassLoaderDataGraph::print_dictionary(outputStream* st) {
FOR_ALL_DICTIONARY(cld) {
st->print("Dictionary for ");
cld->print_value_on(st);
st->cr();
cld->dictionary()->print_on(st);
st->cr();
}
}
void ClassLoaderDataGraph::print_dictionary_statistics(outputStream* st) {
FOR_ALL_DICTIONARY(cld) {
ResourceMark rm;
stringStream tempst;
tempst.print("System Dictionary for %s class loader", cld->loader_name_and_id());
cld->dictionary()->print_table_statistics(st, tempst.as_string());
}
}
GrowableArray<ClassLoaderData*>* ClassLoaderDataGraph::new_clds() {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
assert(_head == NULL || _saved_head != NULL, "remember_new_clds(true) not called?");
GrowableArray<ClassLoaderData*>* array = new GrowableArray<ClassLoaderData*>();
// The CLDs in [_head, _saved_head] were all added during last call to remember_new_clds(true);
ClassLoaderData* curr = _head;
while (curr != _saved_head) {
if (!curr->claimed()) {
array->push(curr);
LogTarget(Debug, class, loader, data) lt;
if (lt.is_enabled()) {
LogStream ls(lt);
ls.print("found new CLD: ");
curr->print_value_on(&ls);
ls.cr();
}
}
curr = curr->_next;
}
return array;
}
#ifndef PRODUCT
bool ClassLoaderDataGraph::contains_loader_data(ClassLoaderData* loader_data) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
for (ClassLoaderData* data = _head; data != NULL; data = data->next()) {
if (loader_data == data) {
return true;
}
}
return false;
}
#endif // PRODUCT
// Move class loader data from main list to the unloaded list for unloading
// and deallocation later.
bool ClassLoaderDataGraph::do_unloading(bool do_cleaning) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
// Indicate whether safepoint cleanup is needed.
_safepoint_cleanup_needed |= do_cleaning;
ClassLoaderData* data = _head;
ClassLoaderData* prev = NULL;
bool seen_dead_loader = false;
uint loaders_processed = 0;
uint loaders_removed = 0;
// Save previous _unloading pointer for CMS which may add to unloading list before
// purging and we don't want to rewalk the previously unloaded class loader data.
_saved_unloading = _unloading;
data = _head;
while (data != NULL) {
if (data->is_alive()) {
prev = data;
data = data->next();
loaders_processed++;
continue;
}
seen_dead_loader = true;
loaders_removed++;
ClassLoaderData* dead = data;
dead->unload();
data = data->next();
// Remove from loader list.
// This class loader data will no longer be found
// in the ClassLoaderDataGraph.
if (prev != NULL) {
prev->set_next(data);
} else {
assert(dead == _head, "sanity check");
_head = data;
}
dead->set_next(_unloading);
_unloading = dead;
}
log_debug(class, loader, data)("do_unloading: loaders processed %u, loaders removed %u", loaders_processed, loaders_removed);
return seen_dead_loader;
}
// There's at least one dead class loader. Purge refererences of healthy module
// reads lists and package export lists to modules belonging to dead loaders.
void ClassLoaderDataGraph::clean_module_and_package_info() {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
ClassLoaderData* data = _head;
while (data != NULL) {
// Remove entries in the dictionary of live class loader that have
// initiated loading classes in a dead class loader.
if (data->dictionary() != NULL) {
data->dictionary()->do_unloading();
}
// Walk a ModuleEntry's reads, and a PackageEntry's exports
// lists to determine if there are modules on those lists that are now
// dead and should be removed. A module's life cycle is equivalent
// to its defining class loader's life cycle. Since a module is
// considered dead if its class loader is dead, these walks must
// occur after each class loader's aliveness is determined.
if (data->packages() != NULL) {
data->packages()->purge_all_package_exports();
}
if (data->modules_defined()) {
data->modules()->purge_all_module_reads();
}
data = data->next();
}
}
void ClassLoaderDataGraph::purge() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
ClassLoaderData* list = _unloading;
_unloading = NULL;
ClassLoaderData* next = list;
bool classes_unloaded = false;
while (next != NULL) {
ClassLoaderData* purge_me = next;
next = purge_me->next();
delete purge_me;
classes_unloaded = true;
}
if (classes_unloaded) {
Metaspace::purge();
set_metaspace_oom(false);
}
}
int ClassLoaderDataGraph::resize_if_needed() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
int resized = 0;
if (Dictionary::does_any_dictionary_needs_resizing()) {
FOR_ALL_DICTIONARY(cld) {
if (cld->dictionary()->resize_if_needed()) {
resized++;
}
}
}
return resized;
}
ClassLoaderDataGraphKlassIteratorAtomic::ClassLoaderDataGraphKlassIteratorAtomic()
: _next_klass(NULL) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
ClassLoaderData* cld = ClassLoaderDataGraph::_head;
Klass* klass = NULL;
// Find the first klass in the CLDG.
while (cld != NULL) {
assert_locked_or_safepoint(cld->metaspace_lock());
klass = cld->_klasses;
if (klass != NULL) {
_next_klass = klass;
return;
}
cld = cld->next();
}
}
Klass* ClassLoaderDataGraphKlassIteratorAtomic::next_klass_in_cldg(Klass* klass) {
Klass* next = klass->next_link();
if (next != NULL) {
return next;
}
// No more klasses in the current CLD. Time to find a new CLD.
ClassLoaderData* cld = klass->class_loader_data();
assert_locked_or_safepoint(cld->metaspace_lock());
while (next == NULL) {
cld = cld->next();
if (cld == NULL) {
break;
}
next = cld->_klasses;
}
return next;
}
Klass* ClassLoaderDataGraphKlassIteratorAtomic::next_klass() {
Klass* head = _next_klass;
while (head != NULL) {
Klass* next = next_klass_in_cldg(head);
Klass* old_head = Atomic::cmpxchg(next, &_next_klass, head);
if (old_head == head) {
return head; // Won the CAS.
}
head = old_head;
}
// Nothing more for the iterator to hand out.
assert(head == NULL, "head is " PTR_FORMAT ", expected not null:", p2i(head));
return NULL;
}
ClassLoaderDataGraphMetaspaceIterator::ClassLoaderDataGraphMetaspaceIterator() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
_data = ClassLoaderDataGraph::_head;
}
ClassLoaderDataGraphMetaspaceIterator::~ClassLoaderDataGraphMetaspaceIterator() {}
#ifndef PRODUCT
// callable from debugger
extern "C" int print_loader_data_graph() {
ResourceMark rm;
ClassLoaderDataGraph::print_on(tty);
return 0;
}
void ClassLoaderDataGraph::verify() {
ClassLoaderDataGraphIterator iter;
while (iter.repeat()) {
ClassLoaderData* cld = iter.get_next();
cld->verify();
}
}
void ClassLoaderDataGraph::print_on(outputStream * const out) {
ClassLoaderDataGraphIterator iter;
while (iter.repeat()) {
ClassLoaderData* cld = iter.get_next();
cld->print_on(out);
}
}
#endif // PRODUCT

View File

@ -53,9 +53,8 @@
// ClassLoaderData are stored in the runtime representation of classes,
// and provides iterators for root tracing and other GC operations.
class ClassLoaderData;
class ClassLoaderDataGraph;
class JNIMethodBlock;
class Metadebug;
class ModuleEntry;
class PackageEntry;
class ModuleEntryTable;
@ -63,136 +62,6 @@ class PackageEntryTable;
class DictionaryEntry;
class Dictionary;
// GC root for walking class loader data created
class ClassLoaderDataGraph : public AllStatic {
friend class ClassLoaderData;
friend class ClassLoaderDataGraphMetaspaceIterator;
friend class ClassLoaderDataGraphKlassIteratorAtomic;
friend class ClassLoaderDataGraphKlassIteratorStatic;
friend class ClassLoaderDataGraphIterator;
friend class VMStructs;
private:
// All CLDs (except the null CLD) can be reached by walking _head->_next->...
static ClassLoaderData* _head;
static ClassLoaderData* _unloading;
// CMS support.
static ClassLoaderData* _saved_head;
static ClassLoaderData* _saved_unloading;
static bool _should_purge;
// Set if there's anything to purge in the deallocate lists or previous versions
// during a safepoint after class unloading in a full GC.
static bool _should_clean_deallocate_lists;
static bool _safepoint_cleanup_needed;
// OOM has been seen in metaspace allocation. Used to prevent some
// allocations until class unloading
static bool _metaspace_oom;
static volatile size_t _num_instance_classes;
static volatile size_t _num_array_classes;
static ClassLoaderData* add_to_graph(Handle class_loader, bool is_unsafe_anonymous);
static ClassLoaderData* add(Handle class_loader, bool is_unsafe_anonymous);
public:
static ClassLoaderData* find_or_create(Handle class_loader);
static void clean_module_and_package_info();
static void purge();
static void clear_claimed_marks();
// Iteration through CLDG inside a safepoint; GC support
static void cld_do(CLDClosure* cl);
static void cld_unloading_do(CLDClosure* cl);
static void roots_cld_do(CLDClosure* strong, CLDClosure* weak);
static void always_strong_cld_do(CLDClosure* cl);
// klass do
// Walking classes through the ClassLoaderDataGraph include array classes. It also includes
// classes that are allocated but not loaded, classes that have errors, and scratch classes
// for redefinition. These classes are removed during the next class unloading.
// Walking the ClassLoaderDataGraph also includes unsafe anonymous classes.
static void classes_do(KlassClosure* klass_closure);
static void classes_do(void f(Klass* const));
static void methods_do(void f(Method*));
static void modules_do(void f(ModuleEntry*));
static void modules_unloading_do(void f(ModuleEntry*));
static void packages_do(void f(PackageEntry*));
static void packages_unloading_do(void f(PackageEntry*));
static void loaded_classes_do(KlassClosure* klass_closure);
static void unlocked_loaded_classes_do(KlassClosure* klass_closure);
static void classes_unloading_do(void f(Klass* const));
static bool do_unloading(bool do_cleaning);
// Expose state to avoid logging overhead in safepoint cleanup tasks.
static inline bool should_clean_metaspaces_and_reset();
static void set_should_clean_deallocate_lists() { _should_clean_deallocate_lists = true; }
static void clean_deallocate_lists(bool purge_previous_versions);
static void walk_metadata_and_clean_metaspaces();
// dictionary do
// Iterate over all klasses in dictionary, but
// just the classes from defining class loaders.
static void dictionary_classes_do(void f(InstanceKlass*));
// Added for initialize_itable_for_klass to handle exceptions.
static void dictionary_classes_do(void f(InstanceKlass*, TRAPS), TRAPS);
// VM_CounterDecay iteration support
static InstanceKlass* try_get_next_class();
static void verify_dictionary();
static void print_dictionary(outputStream* st);
static void print_dictionary_statistics(outputStream* st);
// CMS support.
static void remember_new_clds(bool remember) { _saved_head = (remember ? _head : NULL); }
static GrowableArray<ClassLoaderData*>* new_clds();
static void set_should_purge(bool b) { _should_purge = b; }
static void purge_if_needed() {
// Only purge the CLDG for CMS if concurrent sweep is complete.
if (_should_purge) {
purge();
// reset for next time.
set_should_purge(false);
}
}
static int resize_if_needed();
static bool has_metaspace_oom() { return _metaspace_oom; }
static void set_metaspace_oom(bool value) { _metaspace_oom = value; }
static void print_on(outputStream * const out) PRODUCT_RETURN;
static void print() { print_on(tty); }
static void verify();
// instance and array class counters
static inline size_t num_instance_classes();
static inline size_t num_array_classes();
static inline void inc_instance_classes(size_t count);
static inline void dec_instance_classes(size_t count);
static inline void inc_array_classes(size_t count);
static inline void dec_array_classes(size_t count);
#ifndef PRODUCT
static bool contains_loader_data(ClassLoaderData* loader_data);
#endif
};
class LockedClassesDo : public KlassClosure {
typedef void (*classes_do_func_t)(Klass*);
classes_do_func_t _function;
public:
LockedClassesDo(); // For callers who provide their own do_klass
LockedClassesDo(classes_do_func_t function);
~LockedClassesDo();
void do_klass(Klass* k) {
(*_function)(k);
}
};
// ClassLoaderData class
class ClassLoaderData : public CHeapObj<mtClass> {
@ -448,31 +317,4 @@ class ClassLoaderData : public CHeapObj<mtClass> {
JFR_ONLY(DEFINE_TRACE_ID_METHODS;)
};
// An iterator that distributes Klasses to parallel worker threads.
class ClassLoaderDataGraphKlassIteratorAtomic : public StackObj {
Klass* volatile _next_klass;
public:
ClassLoaderDataGraphKlassIteratorAtomic();
Klass* next_klass();
private:
static Klass* next_klass_in_cldg(Klass* klass);
};
class ClassLoaderDataGraphMetaspaceIterator : public StackObj {
ClassLoaderData* _data;
public:
ClassLoaderDataGraphMetaspaceIterator();
~ClassLoaderDataGraphMetaspaceIterator();
bool repeat() { return _data != NULL; }
ClassLoaderMetaspace* get_next() {
assert(_data != NULL, "Should not be NULL in call to the iterator");
ClassLoaderMetaspace* result = _data->metaspace_or_null();
_data = _data->next();
// This result might be NULL for class loaders without metaspace
// yet. It would be nice to return only non-null results but
// there is no guarantee that there will be a non-null result
// down the list so the caller is going to have to check.
return result;
}
};
#endif // SHARE_VM_CLASSFILE_CLASSLOADERDATA_HPP

View File

@ -55,54 +55,4 @@ inline ClassLoaderData* ClassLoaderData::class_loader_data(oop loader) {
return loader_data;
}
inline ClassLoaderData *ClassLoaderDataGraph::find_or_create(Handle loader) {
guarantee(loader() != NULL && oopDesc::is_oop(loader()), "Loader must be oop");
// Gets the class loader data out of the java/lang/ClassLoader object, if non-null
// it's already in the loader_data, so no need to add
ClassLoaderData* loader_data= java_lang_ClassLoader::loader_data_acquire(loader());
if (loader_data) {
return loader_data;
}
return ClassLoaderDataGraph::add(loader, false);
}
size_t ClassLoaderDataGraph::num_instance_classes() {
return _num_instance_classes;
}
size_t ClassLoaderDataGraph::num_array_classes() {
return _num_array_classes;
}
void ClassLoaderDataGraph::inc_instance_classes(size_t count) {
Atomic::add(count, &_num_instance_classes);
}
void ClassLoaderDataGraph::dec_instance_classes(size_t count) {
assert(count <= _num_instance_classes, "Sanity");
Atomic::sub(count, &_num_instance_classes);
}
void ClassLoaderDataGraph::inc_array_classes(size_t count) {
Atomic::add(count, &_num_array_classes);
}
void ClassLoaderDataGraph::dec_array_classes(size_t count) {
assert(count <= _num_array_classes, "Sanity");
Atomic::sub(count, &_num_array_classes);
}
bool ClassLoaderDataGraph::should_clean_metaspaces_and_reset() {
// Only clean metaspaces after full GC.
bool do_cleaning = _safepoint_cleanup_needed;
#if INCLUDE_JVMTI
do_cleaning = do_cleaning && (_should_clean_deallocate_lists || InstanceKlass::has_previous_versions());
#else
do_cleaning = do_cleaning && _should_clean_deallocate_lists;
#endif
_safepoint_cleanup_needed = false; // reset
return do_cleaning;
}
#endif // SHARE_VM_CLASSFILE_CLASSLOADERDATA_INLINE_HPP

View File

@ -0,0 +1,697 @@
/*
* Copyright (c) 2018, 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 "classfile/classLoaderDataGraph.inline.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/metadataOnStackMark.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/packageEntry.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/metaspace.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/atomic.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/mutex.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/safepointVerifiers.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
volatile size_t ClassLoaderDataGraph::_num_array_classes = 0;
volatile size_t ClassLoaderDataGraph::_num_instance_classes = 0;
void ClassLoaderDataGraph::clear_claimed_marks() {
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
cld->clear_claimed();
}
}
// Class iterator used by the compiler. It gets some number of classes at
// a safepoint to decay invocation counters on the methods.
class ClassLoaderDataGraphKlassIteratorStatic {
ClassLoaderData* _current_loader_data;
Klass* _current_class_entry;
public:
ClassLoaderDataGraphKlassIteratorStatic() : _current_loader_data(NULL), _current_class_entry(NULL) {}
InstanceKlass* try_get_next_class() {
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
size_t max_classes = ClassLoaderDataGraph::num_instance_classes();
assert(max_classes > 0, "should not be called with no instance classes");
for (size_t i = 0; i < max_classes; ) {
if (_current_class_entry != NULL) {
Klass* k = _current_class_entry;
_current_class_entry = _current_class_entry->next_link();
if (k->is_instance_klass()) {
InstanceKlass* ik = InstanceKlass::cast(k);
i++; // count all instance classes found
// Not yet loaded classes are counted in max_classes
// but only return loaded classes.
if (ik->is_loaded()) {
return ik;
}
}
} else {
// Go to next CLD
if (_current_loader_data != NULL) {
_current_loader_data = _current_loader_data->next();
}
// Start at the beginning
if (_current_loader_data == NULL) {
_current_loader_data = ClassLoaderDataGraph::_head;
}
_current_class_entry = _current_loader_data->klasses();
}
}
// Should never be reached unless all instance classes have failed or are not fully loaded.
// Caller handles NULL.
return NULL;
}
// If the current class for the static iterator is a class being unloaded or
// deallocated, adjust the current class.
void adjust_saved_class(ClassLoaderData* cld) {
if (_current_loader_data == cld) {
_current_loader_data = cld->next();
if (_current_loader_data != NULL) {
_current_class_entry = _current_loader_data->klasses();
} // else try_get_next_class will start at the head
}
}
void adjust_saved_class(Klass* klass) {
if (_current_class_entry == klass) {
_current_class_entry = klass->next_link();
}
}
};
static ClassLoaderDataGraphKlassIteratorStatic static_klass_iterator;
InstanceKlass* ClassLoaderDataGraph::try_get_next_class() {
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
return static_klass_iterator.try_get_next_class();
}
void ClassLoaderDataGraph::adjust_saved_class(ClassLoaderData* cld) {
return static_klass_iterator.adjust_saved_class(cld);
}
void ClassLoaderDataGraph::adjust_saved_class(Klass* klass) {
return static_klass_iterator.adjust_saved_class(klass);
}
void ClassLoaderDataGraph::clean_deallocate_lists(bool walk_previous_versions) {
assert(SafepointSynchronize::is_at_safepoint(), "must only be called at safepoint");
uint loaders_processed = 0;
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
// is_alive check will be necessary for concurrent class unloading.
if (cld->is_alive()) {
// clean metaspace
if (walk_previous_versions) {
cld->classes_do(InstanceKlass::purge_previous_versions);
}
cld->free_deallocate_list();
loaders_processed++;
}
}
log_debug(class, loader, data)("clean_deallocate_lists: loaders processed %u %s",
loaders_processed, walk_previous_versions ? "walk_previous_versions" : "");
}
void ClassLoaderDataGraph::walk_metadata_and_clean_metaspaces() {
assert(SafepointSynchronize::is_at_safepoint(), "must only be called at safepoint");
_should_clean_deallocate_lists = false; // assume everything gets cleaned
// Mark metadata seen on the stack so we can delete unreferenced entries.
// Walk all metadata, including the expensive code cache walk, only for class redefinition.
// The MetadataOnStackMark walk during redefinition saves previous versions if it finds old methods
// on the stack or in the code cache, so we only have to repeat the full walk if
// they were found at that time.
// TODO: have redefinition clean old methods out of the code cache. They still exist in some places.
bool walk_all_metadata = InstanceKlass::has_previous_versions_and_reset();
MetadataOnStackMark md_on_stack(walk_all_metadata);
clean_deallocate_lists(walk_all_metadata);
}
// GC root of class loader data created.
ClassLoaderData* ClassLoaderDataGraph::_head = NULL;
ClassLoaderData* ClassLoaderDataGraph::_unloading = NULL;
ClassLoaderData* ClassLoaderDataGraph::_saved_unloading = NULL;
ClassLoaderData* ClassLoaderDataGraph::_saved_head = NULL;
bool ClassLoaderDataGraph::_should_purge = false;
bool ClassLoaderDataGraph::_should_clean_deallocate_lists = false;
bool ClassLoaderDataGraph::_safepoint_cleanup_needed = false;
bool ClassLoaderDataGraph::_metaspace_oom = false;
// Add a new class loader data node to the list. Assign the newly created
// ClassLoaderData into the java/lang/ClassLoader object as a hidden field
ClassLoaderData* ClassLoaderDataGraph::add_to_graph(Handle loader, bool is_unsafe_anonymous) {
assert_lock_strong(ClassLoaderDataGraph_lock);
ClassLoaderData* cld;
// First check if another thread beat us to creating the CLD and installing
// it into the loader while we were waiting for the lock.
if (!is_unsafe_anonymous && loader.not_null()) {
cld = java_lang_ClassLoader::loader_data_acquire(loader());
if (cld != NULL) {
return cld;
}
}
// We mustn't GC until we've installed the ClassLoaderData in the Graph since the CLD
// contains oops in _handles that must be walked. GC doesn't walk CLD from the
// loader oop in all collections, particularly young collections.
NoSafepointVerifier no_safepoints;
cld = new ClassLoaderData(loader, is_unsafe_anonymous);
// First install the new CLD to the Graph.
cld->set_next(_head);
_head = cld;
// Next associate with the class_loader.
if (!is_unsafe_anonymous) {
// Use OrderAccess, since readers need to get the loader_data only after
// it's added to the Graph
java_lang_ClassLoader::release_set_loader_data(loader(), cld);
}
// Lastly log, if requested
LogTarget(Trace, class, loader, data) lt;
if (lt.is_enabled()) {
ResourceMark rm;
LogStream ls(lt);
ls.print("create ");
cld->print_value_on(&ls);
ls.cr();
}
return cld;
}
ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_unsafe_anonymous) {
MutexLocker ml(ClassLoaderDataGraph_lock);
ClassLoaderData* loader_data = add_to_graph(loader, is_unsafe_anonymous);
return loader_data;
}
void ClassLoaderDataGraph::cld_do(CLDClosure* cl) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->_next) {
cl->do_cld(cld);
}
}
void ClassLoaderDataGraph::cld_unloading_do(CLDClosure* cl) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
// Only walk the head until any clds not purged from prior unloading
// (CMS doesn't purge right away).
for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
assert(cld->is_unloading(), "invariant");
cl->do_cld(cld);
}
}
void ClassLoaderDataGraph::roots_cld_do(CLDClosure* strong, CLDClosure* weak) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->_next) {
CLDClosure* closure = cld->keep_alive() ? strong : weak;
if (closure != NULL) {
closure->do_cld(cld);
}
}
}
void ClassLoaderDataGraph::always_strong_cld_do(CLDClosure* cl) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
if (ClassUnloading) {
roots_cld_do(cl, NULL);
} else {
cld_do(cl);
}
}
// Closure for locking and iterating through classes.
LockedClassesDo::LockedClassesDo(classes_do_func_t f) : _function(f) {
ClassLoaderDataGraph_lock->lock();
}
LockedClassesDo::LockedClassesDo() : _function(NULL) {
// callers provide their own do_klass
ClassLoaderDataGraph_lock->lock();
}
LockedClassesDo::~LockedClassesDo() { ClassLoaderDataGraph_lock->unlock(); }
// Iterating over the CLDG needs to be locked because
// unloading can remove entries concurrently soon.
class ClassLoaderDataGraphIterator : public StackObj {
ClassLoaderData* _next;
HandleMark _hm; // clean up handles when this is done.
Handle _holder;
Thread* _thread;
void hold_next() {
if (_next != NULL) {
_holder = Handle(_thread, _next->holder_phantom());
}
}
public:
ClassLoaderDataGraphIterator() : _next(ClassLoaderDataGraph::_head) {
_thread = Thread::current();
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
hold_next();
}
bool repeat() const {
return _next != NULL;
}
ClassLoaderData* get_next() {
ClassLoaderData* next = _next;
if (_next != NULL) {
_next = _next->next();
hold_next();
}
return next;
}
};
// These functions assume that the caller has locked the ClassLoaderDataGraph_lock
// if they are not calling the function from a safepoint.
void ClassLoaderDataGraph::classes_do(KlassClosure* klass_closure) {
ClassLoaderDataGraphIterator iter;
while (iter.repeat()) {
ClassLoaderData* cld = iter.get_next();
cld->classes_do(klass_closure);
}
}
void ClassLoaderDataGraph::classes_do(void f(Klass* const)) {
ClassLoaderDataGraphIterator iter;
while (iter.repeat()) {
ClassLoaderData* cld = iter.get_next();
cld->classes_do(f);
}
}
void ClassLoaderDataGraph::methods_do(void f(Method*)) {
ClassLoaderDataGraphIterator iter;
while (iter.repeat()) {
ClassLoaderData* cld = iter.get_next();
cld->methods_do(f);
}
}
void ClassLoaderDataGraph::modules_do(void f(ModuleEntry*)) {
assert_locked_or_safepoint(Module_lock);
ClassLoaderDataGraphIterator iter;
while (iter.repeat()) {
ClassLoaderData* cld = iter.get_next();
cld->modules_do(f);
}
}
void ClassLoaderDataGraph::modules_unloading_do(void f(ModuleEntry*)) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
// Only walk the head until any clds not purged from prior unloading
// (CMS doesn't purge right away).
for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
assert(cld->is_unloading(), "invariant");
cld->modules_do(f);
}
}
void ClassLoaderDataGraph::packages_do(void f(PackageEntry*)) {
assert_locked_or_safepoint(Module_lock);
ClassLoaderDataGraphIterator iter;
while (iter.repeat()) {
ClassLoaderData* cld = iter.get_next();
cld->packages_do(f);
}
}
void ClassLoaderDataGraph::packages_unloading_do(void f(PackageEntry*)) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
// Only walk the head until any clds not purged from prior unloading
// (CMS doesn't purge right away).
for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
assert(cld->is_unloading(), "invariant");
cld->packages_do(f);
}
}
void ClassLoaderDataGraph::loaded_classes_do(KlassClosure* klass_closure) {
ClassLoaderDataGraphIterator iter;
while (iter.repeat()) {
ClassLoaderData* cld = iter.get_next();
cld->loaded_classes_do(klass_closure);
}
}
// This case can block but cannot do unloading (called from CDS)
void ClassLoaderDataGraph::unlocked_loaded_classes_do(KlassClosure* klass_closure) {
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
cld->loaded_classes_do(klass_closure);
}
}
void ClassLoaderDataGraph::classes_unloading_do(void f(Klass* const)) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
// Only walk the head until any clds not purged from prior unloading
// (CMS doesn't purge right away).
for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
assert(cld->is_unloading(), "invariant");
cld->classes_do(f);
}
}
#define FOR_ALL_DICTIONARY(X) ClassLoaderDataGraphIterator iter; \
ClassLoaderData* X; \
while ((X = iter.get_next()) != NULL) \
if (X->dictionary() != NULL)
// Walk classes in the loaded class dictionaries in various forms.
// Only walks the classes defined in this class loader.
void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*)) {
FOR_ALL_DICTIONARY(cld) {
cld->dictionary()->classes_do(f);
}
}
// Only walks the classes defined in this class loader.
void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*, TRAPS), TRAPS) {
FOR_ALL_DICTIONARY(cld) {
cld->dictionary()->classes_do(f, CHECK);
}
}
void ClassLoaderDataGraph::verify_dictionary() {
FOR_ALL_DICTIONARY(cld) {
cld->dictionary()->verify();
}
}
void ClassLoaderDataGraph::print_dictionary(outputStream* st) {
FOR_ALL_DICTIONARY(cld) {
st->print("Dictionary for ");
cld->print_value_on(st);
st->cr();
cld->dictionary()->print_on(st);
st->cr();
}
}
void ClassLoaderDataGraph::print_dictionary_statistics(outputStream* st) {
FOR_ALL_DICTIONARY(cld) {
ResourceMark rm;
stringStream tempst;
tempst.print("System Dictionary for %s class loader", cld->loader_name_and_id());
cld->dictionary()->print_table_statistics(st, tempst.as_string());
}
}
GrowableArray<ClassLoaderData*>* ClassLoaderDataGraph::new_clds() {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
assert(_head == NULL || _saved_head != NULL, "remember_new_clds(true) not called?");
GrowableArray<ClassLoaderData*>* array = new GrowableArray<ClassLoaderData*>();
// The CLDs in [_head, _saved_head] were all added during last call to remember_new_clds(true);
ClassLoaderData* curr = _head;
while (curr != _saved_head) {
if (!curr->claimed()) {
array->push(curr);
LogTarget(Debug, class, loader, data) lt;
if (lt.is_enabled()) {
LogStream ls(lt);
ls.print("found new CLD: ");
curr->print_value_on(&ls);
ls.cr();
}
}
curr = curr->_next;
}
return array;
}
#ifndef PRODUCT
bool ClassLoaderDataGraph::contains_loader_data(ClassLoaderData* loader_data) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
for (ClassLoaderData* data = _head; data != NULL; data = data->next()) {
if (loader_data == data) {
return true;
}
}
return false;
}
#endif // PRODUCT
// Move class loader data from main list to the unloaded list for unloading
// and deallocation later.
bool ClassLoaderDataGraph::do_unloading(bool do_cleaning) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
// Indicate whether safepoint cleanup is needed.
_safepoint_cleanup_needed |= do_cleaning;
ClassLoaderData* data = _head;
ClassLoaderData* prev = NULL;
bool seen_dead_loader = false;
uint loaders_processed = 0;
uint loaders_removed = 0;
// Save previous _unloading pointer for CMS which may add to unloading list before
// purging and we don't want to rewalk the previously unloaded class loader data.
_saved_unloading = _unloading;
data = _head;
while (data != NULL) {
if (data->is_alive()) {
prev = data;
data = data->next();
loaders_processed++;
continue;
}
seen_dead_loader = true;
loaders_removed++;
ClassLoaderData* dead = data;
dead->unload();
data = data->next();
// Remove from loader list.
// This class loader data will no longer be found
// in the ClassLoaderDataGraph.
if (prev != NULL) {
prev->set_next(data);
} else {
assert(dead == _head, "sanity check");
_head = data;
}
dead->set_next(_unloading);
_unloading = dead;
}
log_debug(class, loader, data)("do_unloading: loaders processed %u, loaders removed %u", loaders_processed, loaders_removed);
return seen_dead_loader;
}
// There's at least one dead class loader. Purge refererences of healthy module
// reads lists and package export lists to modules belonging to dead loaders.
void ClassLoaderDataGraph::clean_module_and_package_info() {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
ClassLoaderData* data = _head;
while (data != NULL) {
// Remove entries in the dictionary of live class loader that have
// initiated loading classes in a dead class loader.
if (data->dictionary() != NULL) {
data->dictionary()->do_unloading();
}
// Walk a ModuleEntry's reads, and a PackageEntry's exports
// lists to determine if there are modules on those lists that are now
// dead and should be removed. A module's life cycle is equivalent
// to its defining class loader's life cycle. Since a module is
// considered dead if its class loader is dead, these walks must
// occur after each class loader's aliveness is determined.
if (data->packages() != NULL) {
data->packages()->purge_all_package_exports();
}
if (data->modules_defined()) {
data->modules()->purge_all_module_reads();
}
data = data->next();
}
}
void ClassLoaderDataGraph::purge() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
ClassLoaderData* list = _unloading;
_unloading = NULL;
ClassLoaderData* next = list;
bool classes_unloaded = false;
while (next != NULL) {
ClassLoaderData* purge_me = next;
next = purge_me->next();
delete purge_me;
classes_unloaded = true;
}
if (classes_unloaded) {
Metaspace::purge();
set_metaspace_oom(false);
}
}
int ClassLoaderDataGraph::resize_if_needed() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
int resized = 0;
if (Dictionary::does_any_dictionary_needs_resizing()) {
FOR_ALL_DICTIONARY(cld) {
if (cld->dictionary()->resize_if_needed()) {
resized++;
}
}
}
return resized;
}
ClassLoaderDataGraphKlassIteratorAtomic::ClassLoaderDataGraphKlassIteratorAtomic()
: _next_klass(NULL) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
ClassLoaderData* cld = ClassLoaderDataGraph::_head;
Klass* klass = NULL;
// Find the first klass in the CLDG.
while (cld != NULL) {
assert_locked_or_safepoint(cld->metaspace_lock());
klass = cld->_klasses;
if (klass != NULL) {
_next_klass = klass;
return;
}
cld = cld->next();
}
}
Klass* ClassLoaderDataGraphKlassIteratorAtomic::next_klass_in_cldg(Klass* klass) {
Klass* next = klass->next_link();
if (next != NULL) {
return next;
}
// No more klasses in the current CLD. Time to find a new CLD.
ClassLoaderData* cld = klass->class_loader_data();
assert_locked_or_safepoint(cld->metaspace_lock());
while (next == NULL) {
cld = cld->next();
if (cld == NULL) {
break;
}
next = cld->_klasses;
}
return next;
}
Klass* ClassLoaderDataGraphKlassIteratorAtomic::next_klass() {
Klass* head = _next_klass;
while (head != NULL) {
Klass* next = next_klass_in_cldg(head);
Klass* old_head = Atomic::cmpxchg(next, &_next_klass, head);
if (old_head == head) {
return head; // Won the CAS.
}
head = old_head;
}
// Nothing more for the iterator to hand out.
assert(head == NULL, "head is " PTR_FORMAT ", expected not null:", p2i(head));
return NULL;
}
ClassLoaderDataGraphMetaspaceIterator::ClassLoaderDataGraphMetaspaceIterator() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
_data = ClassLoaderDataGraph::_head;
}
ClassLoaderDataGraphMetaspaceIterator::~ClassLoaderDataGraphMetaspaceIterator() {}
ClassLoaderMetaspace* ClassLoaderDataGraphMetaspaceIterator::get_next() {
assert(_data != NULL, "Should not be NULL in call to the iterator");
ClassLoaderMetaspace* result = _data->metaspace_or_null();
_data = _data->next();
// This result might be NULL for class loaders without metaspace
// yet. It would be nice to return only non-null results but
// there is no guarantee that there will be a non-null result
// down the list so the caller is going to have to check.
return result;
}
#ifndef PRODUCT
// callable from debugger
extern "C" int print_loader_data_graph() {
ResourceMark rm;
ClassLoaderDataGraph::print_on(tty);
return 0;
}
void ClassLoaderDataGraph::verify() {
ClassLoaderDataGraphIterator iter;
while (iter.repeat()) {
ClassLoaderData* cld = iter.get_next();
cld->verify();
}
}
void ClassLoaderDataGraph::print_on(outputStream * const out) {
ClassLoaderDataGraphIterator iter;
while (iter.repeat()) {
ClassLoaderData* cld = iter.get_next();
cld->print_on(out);
}
}
#endif // PRODUCT

View File

@ -0,0 +1,182 @@
/*
* Copyright (c) 2018, 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_CLASSFILE_CLASSLOADERDATAGRAPH_HPP
#define SHARE_VM_CLASSFILE_CLASSLOADERDATAGRAPH_HPP
#include "classfile/classLoaderData.hpp"
#include "memory/allocation.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
// GC root for walking class loader data created
class ClassLoaderDataGraph : public AllStatic {
friend class ClassLoaderData;
friend class ClassLoaderDataGraphMetaspaceIterator;
friend class ClassLoaderDataGraphKlassIteratorAtomic;
friend class ClassLoaderDataGraphKlassIteratorStatic;
friend class ClassLoaderDataGraphIterator;
friend class VMStructs;
private:
// All CLDs (except the null CLD) can be reached by walking _head->_next->...
static ClassLoaderData* _head;
static ClassLoaderData* _unloading;
// CMS support.
static ClassLoaderData* _saved_head;
static ClassLoaderData* _saved_unloading;
static bool _should_purge;
// Set if there's anything to purge in the deallocate lists or previous versions
// during a safepoint after class unloading in a full GC.
static bool _should_clean_deallocate_lists;
static bool _safepoint_cleanup_needed;
// OOM has been seen in metaspace allocation. Used to prevent some
// allocations until class unloading
static bool _metaspace_oom;
static volatile size_t _num_instance_classes;
static volatile size_t _num_array_classes;
static ClassLoaderData* add_to_graph(Handle class_loader, bool is_unsafe_anonymous);
static ClassLoaderData* add(Handle class_loader, bool is_unsafe_anonymous);
public:
static ClassLoaderData* find_or_create(Handle class_loader);
static void clean_module_and_package_info();
static void purge();
static void clear_claimed_marks();
// Iteration through CLDG inside a safepoint; GC support
static void cld_do(CLDClosure* cl);
static void cld_unloading_do(CLDClosure* cl);
static void roots_cld_do(CLDClosure* strong, CLDClosure* weak);
static void always_strong_cld_do(CLDClosure* cl);
// klass do
// Walking classes through the ClassLoaderDataGraph include array classes. It also includes
// classes that are allocated but not loaded, classes that have errors, and scratch classes
// for redefinition. These classes are removed during the next class unloading.
// Walking the ClassLoaderDataGraph also includes unsafe anonymous classes.
static void classes_do(KlassClosure* klass_closure);
static void classes_do(void f(Klass* const));
static void methods_do(void f(Method*));
static void modules_do(void f(ModuleEntry*));
static void modules_unloading_do(void f(ModuleEntry*));
static void packages_do(void f(PackageEntry*));
static void packages_unloading_do(void f(PackageEntry*));
static void loaded_classes_do(KlassClosure* klass_closure);
static void unlocked_loaded_classes_do(KlassClosure* klass_closure);
static void classes_unloading_do(void f(Klass* const));
static bool do_unloading(bool do_cleaning);
// Expose state to avoid logging overhead in safepoint cleanup tasks.
static inline bool should_clean_metaspaces_and_reset();
static void set_should_clean_deallocate_lists() { _should_clean_deallocate_lists = true; }
static void clean_deallocate_lists(bool purge_previous_versions);
static void walk_metadata_and_clean_metaspaces();
// dictionary do
// Iterate over all klasses in dictionary, but
// just the classes from defining class loaders.
static void dictionary_classes_do(void f(InstanceKlass*));
// Added for initialize_itable_for_klass to handle exceptions.
static void dictionary_classes_do(void f(InstanceKlass*, TRAPS), TRAPS);
// VM_CounterDecay iteration support
static InstanceKlass* try_get_next_class();
static void adjust_saved_class(ClassLoaderData* cld);
static void adjust_saved_class(Klass* klass);
static void verify_dictionary();
static void print_dictionary(outputStream* st);
static void print_dictionary_statistics(outputStream* st);
// CMS support.
static void remember_new_clds(bool remember) { _saved_head = (remember ? _head : NULL); }
static GrowableArray<ClassLoaderData*>* new_clds();
static void set_should_purge(bool b) { _should_purge = b; }
static void purge_if_needed() {
// Only purge the CLDG for CMS if concurrent sweep is complete.
if (_should_purge) {
purge();
// reset for next time.
set_should_purge(false);
}
}
static int resize_if_needed();
static bool has_metaspace_oom() { return _metaspace_oom; }
static void set_metaspace_oom(bool value) { _metaspace_oom = value; }
static void print_on(outputStream * const out) PRODUCT_RETURN;
static void print() { print_on(tty); }
static void verify();
// instance and array class counters
static inline size_t num_instance_classes();
static inline size_t num_array_classes();
static inline void inc_instance_classes(size_t count);
static inline void dec_instance_classes(size_t count);
static inline void inc_array_classes(size_t count);
static inline void dec_array_classes(size_t count);
#ifndef PRODUCT
static bool contains_loader_data(ClassLoaderData* loader_data);
#endif
};
class LockedClassesDo : public KlassClosure {
typedef void (*classes_do_func_t)(Klass*);
classes_do_func_t _function;
public:
LockedClassesDo(); // For callers who provide their own do_klass
LockedClassesDo(classes_do_func_t function);
~LockedClassesDo();
void do_klass(Klass* k) {
(*_function)(k);
}
};
// An iterator that distributes Klasses to parallel worker threads.
class ClassLoaderDataGraphKlassIteratorAtomic : public StackObj {
Klass* volatile _next_klass;
public:
ClassLoaderDataGraphKlassIteratorAtomic();
Klass* next_klass();
private:
static Klass* next_klass_in_cldg(Klass* klass);
};
class ClassLoaderDataGraphMetaspaceIterator : public StackObj {
ClassLoaderData* _data;
public:
ClassLoaderDataGraphMetaspaceIterator();
~ClassLoaderDataGraphMetaspaceIterator();
bool repeat() { return _data != NULL; }
ClassLoaderMetaspace* get_next();
};
#endif // SHARE_VM_CLASSFILE_CLASSLOADERDATAGRAPH_HPP

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2018, 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_CLASSFILE_CLASSLOADERDATAGRAPH_INLINE_HPP
#define SHARE_VM_CLASSFILE_CLASSLOADERDATAGRAPH_INLINE_HPP
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/javaClasses.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
inline ClassLoaderData *ClassLoaderDataGraph::find_or_create(Handle loader) {
guarantee(loader() != NULL && oopDesc::is_oop(loader()), "Loader must be oop");
// Gets the class loader data out of the java/lang/ClassLoader object, if non-null
// it's already in the loader_data, so no need to add
ClassLoaderData* loader_data = java_lang_ClassLoader::loader_data_acquire(loader());
if (loader_data) {
return loader_data;
}
return ClassLoaderDataGraph::add(loader, false);
}
size_t ClassLoaderDataGraph::num_instance_classes() {
return _num_instance_classes;
}
size_t ClassLoaderDataGraph::num_array_classes() {
return _num_array_classes;
}
void ClassLoaderDataGraph::inc_instance_classes(size_t count) {
Atomic::add(count, &_num_instance_classes);
}
void ClassLoaderDataGraph::dec_instance_classes(size_t count) {
assert(count <= _num_instance_classes, "Sanity");
Atomic::sub(count, &_num_instance_classes);
}
void ClassLoaderDataGraph::inc_array_classes(size_t count) {
Atomic::add(count, &_num_array_classes);
}
void ClassLoaderDataGraph::dec_array_classes(size_t count) {
assert(count <= _num_array_classes, "Sanity");
Atomic::sub(count, &_num_array_classes);
}
bool ClassLoaderDataGraph::should_clean_metaspaces_and_reset() {
// Only clean metaspaces after full GC.
bool do_cleaning = _safepoint_cleanup_needed;
#if INCLUDE_JVMTI
do_cleaning = do_cleaning && (_should_clean_deallocate_lists || InstanceKlass::has_previous_versions());
#else
do_cleaning = do_cleaning && _should_clean_deallocate_lists;
#endif
_safepoint_cleanup_needed = false; // reset
return do_cleaning;
}
#endif // SHARE_VM_CLASSFILE_CLASSLOADERDATAGRAPH_INLINE_HPP

View File

@ -26,6 +26,7 @@
#include "precompiled.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/classLoaderHierarchyDCmd.hpp"
#include "memory/allocation.hpp"
#include "memory/resourceArea.hpp"

View File

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/classLoaderStats.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/globalDefinitions.hpp"

View File

@ -23,8 +23,9 @@
*/
#include "precompiled.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/loaderConstraints.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"

View File

@ -29,6 +29,7 @@
#include "classfile/classFileStream.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderDataGraph.inline.hpp"
#include "classfile/classLoaderExt.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/javaClasses.inline.hpp"

View File

@ -218,18 +218,6 @@ int DependencyContext::remove_all_dependents() {
return marked;
}
void DependencyContext::wipe() {
assert_locked_or_safepoint(CodeCache_lock);
nmethodBucket* b = dependencies();
set_dependencies(NULL);
set_has_stale_entries(false);
while (b != NULL) {
nmethodBucket* next = b->next();
delete b;
b = next;
}
}
#ifndef PRODUCT
void DependencyContext::print_dependent_nmethods(bool verbose) {
int idx = 0;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2018, 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
@ -141,10 +141,6 @@ class DependencyContext : public StackObj {
void expunge_stale_entries();
// Unsafe deallocation of nmethodBuckets. Used in IK::release_C_heap_structures
// to clean up the context possibly containing live entries pointing to unloaded nmethods.
void wipe();
#ifndef PRODUCT
void print_dependent_nmethods(bool verbose);
bool is_dependent_nmethod(nmethod* nm);

View File

@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"

View File

@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/metadataOnStackMark.hpp"
#include "classfile/stringTable.hpp"
#include "code/codeCache.hpp"

View File

@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/metadataOnStackMark.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "code/codeCache.hpp"
#include "gc/g1/g1BarrierSet.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"

View File

@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "gc/g1/g1Analytics.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1ConcurrentMark.inline.hpp"

View File

@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "gc/g1/g1CollectedHeap.hpp"
#include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
#include "gc/g1/g1FullCollector.hpp"

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "gc/g1/g1CollectedHeap.hpp"
#include "gc/g1/g1FullCollector.hpp"
#include "gc/g1/g1FullGCMarker.hpp"

View File

@ -23,8 +23,8 @@
*/
#include "precompiled.hpp"
#include "aot/aotLoader.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"

View File

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "aot/aotLoader.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
#include "gc/parallel/parallelScavengeHeap.hpp"

View File

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "aot/aotLoader.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"

View File

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "aot/aotLoader.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"

View File

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "aot/aotLoader.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
#include "gc/parallel/gcTaskManager.hpp"

View File

@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"

View File

@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "gc/shared/cardTableRS.hpp"
#include "gc/shared/genCollectedHeap.hpp"
#include "gc/shared/genOopClosures.hpp"

View File

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "aot/aotLoader.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/systemDictionary.hpp"

View File

@ -34,9 +34,9 @@
// These fascilities are used for allocating, and initializing newly allocated objects.
class MemAllocator: StackObj {
protected:
class Allocation;
protected:
CollectedHeap* const _heap;
Thread* const _thread;
Klass* const _klass;

View File

@ -25,6 +25,7 @@
#ifndef SHARE_VM_GC_SHARED_PARALLELCLEANING_HPP
#define SHARE_VM_GC_SHARED_PARALLELCLEANING_HPP
#include "classfile/classLoaderDataGraph.inline.hpp"
#include "gc/shared/oopStorageParState.hpp"
#include "gc/shared/stringdedup/stringDedup.hpp"
#include "gc/shared/workgroup.hpp"

View File

@ -22,7 +22,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"

View File

@ -24,7 +24,7 @@
#include "precompiled.hpp"
#include "aot/aotLoader.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc/shared/strongRootsScope.hpp"

View File

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "aot/aotLoader.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/stringTable.hpp"
#include "gc/shared/strongRootsScope.hpp"
#include "jfr/leakprofiler/utilities/unifiedOop.hpp"

View File

@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "jfr/leakprofiler/utilities/saveRestore.hpp"
#include "oops/oop.inline.hpp"

View File

@ -23,7 +23,8 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/packageEntry.hpp"
#include "jfr/jfrEvents.hpp"

View File

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "jvm.h"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/classLoaderStats.hpp"
#include "classfile/javaClasses.hpp"
#include "code/codeCache.hpp"

View File

@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/packageEntry.hpp"

View File

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc/shared/collectedHeap.hpp"

View File

@ -23,8 +23,8 @@
*/
#include "precompiled.hpp"
#include "aot/aotLoader.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"

View File

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "jvm.h"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/classListParser.hpp"
#include "classfile/classLoaderExt.hpp"
#include "classfile/dictionary.hpp"

View File

@ -25,7 +25,7 @@
#include "precompiled.hpp"
#include "aot/aotLoader.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/systemDictionary.hpp"

View File

@ -686,15 +686,6 @@ bool InstanceKlass::verify_code(TRAPS) {
return Verifier::verify(this, should_verify_class(), THREAD);
}
// Used exclusively by the shared spaces dump mechanism to prevent
// classes mapped into the shared regions in new VMs from appearing linked.
void InstanceKlass::unlink_class() {
assert(is_linked(), "must be linked");
_init_state = loaded;
}
void InstanceKlass::link_class(TRAPS) {
assert(is_loaded(), "must be loaded");
if (!is_linked()) {
@ -2300,10 +2291,12 @@ void InstanceKlass::remove_unshareable_info() {
return;
}
// Unlink the class
if (is_linked()) {
unlink_class();
}
// Reset to the 'allocated' state to prevent any premature accessing to
// a shared class at runtime while the class is still being loaded and
// restored. A class' init_state is set to 'loaded' at runtime when it's
// being added to class hierarchy (see SystemDictionary:::add_to_hierarchy()).
_init_state = allocated;
{
MutexLocker ml(Compile_lock);
init_implementor();
@ -2350,6 +2343,10 @@ void InstanceKlass::remove_java_mirror() {
}
void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
// SystemDictionary::add_to_hierarchy() sets the init_state to loaded
// before the InstanceKlass is added to the SystemDictionary. Make
// sure the current state is <loaded.
assert(!is_loaded(), "invalid init state");
set_package(loader_data, CHECK);
Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
@ -2417,7 +2414,10 @@ static void clear_all_breakpoints(Method* m) {
}
#endif
void InstanceKlass::notify_unload_class(InstanceKlass* ik) {
void InstanceKlass::unload_class(InstanceKlass* ik) {
// Release dependencies.
ik->dependencies().remove_all_dependents();
// notify the debugger
if (JvmtiExport::should_post_class_unload()) {
JvmtiExport::post_class_unload(ik);
@ -2462,16 +2462,8 @@ void InstanceKlass::release_C_heap_structures() {
FreeHeap(jmeths);
}
// Release dependencies.
// It is desirable to use DC::remove_all_dependents() here, but, unfortunately,
// it is not safe (see JDK-8143408). The problem is that the klass dependency
// context can contain live dependencies, since there's a race between nmethod &
// klass unloading. If the klass is dead when nmethod unloading happens, relevant
// dependencies aren't removed from the context associated with the class (see
// nmethod::flush_dependencies). It ends up during klass unloading as seemingly
// live dependencies pointing to unloaded nmethods and causes a crash in
// DC::remove_all_dependents() when it touches unloaded nmethod.
dependencies().wipe();
assert(_dep_context == DependencyContext::EMPTY,
"dependencies should already be cleaned");
#if INCLUDE_JVMTI
// Deallocate breakpoint records

View File

@ -542,7 +542,6 @@ public:
void initialize(TRAPS);
void link_class(TRAPS);
bool link_class_or_fail(TRAPS); // returns false on failure
void unlink_class();
void rewrite_class(TRAPS);
void link_methods(TRAPS);
Method* class_initializer() const;
@ -1180,7 +1179,7 @@ public:
bool on_stack() const { return _constants->on_stack(); }
// callbacks for actions during class unloading
static void notify_unload_class(InstanceKlass* ik);
static void unload_class(InstanceKlass* ik);
static void release_C_heap_structures(InstanceKlass* ik);
// Naming

View File

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "jvm.h"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"

View File

@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/metadataOnStackMark.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"

View File

@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/systemDictionary.hpp"
#include "jvmtifiles/jvmtiEnv.hpp"
#include "memory/resourceArea.hpp"

View File

@ -23,8 +23,8 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "memory/universe.hpp"

View File

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "aot/aotLoader.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/classFileStream.hpp"
#include "classfile/metadataOnStackMark.hpp"
#include "classfile/systemDictionary.hpp"

View File

@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"

View File

@ -26,7 +26,7 @@
#include <new>
#include "classfile/classLoaderData.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/modules.hpp"
#include "classfile/protectionDomainCache.hpp"
#include "classfile/stringTable.hpp"

View File

@ -542,6 +542,7 @@ static SpecialFlag const special_jvm_flags[] = {
{ "CreateMinidumpOnCrash", JDK_Version::jdk(9), JDK_Version::undefined(), JDK_Version::undefined() },
{ "MustCallLoadClassInternal", JDK_Version::jdk(10), JDK_Version::jdk(11), JDK_Version::jdk(12) },
{ "UnsyncloadClass", JDK_Version::jdk(10), JDK_Version::jdk(11), JDK_Version::jdk(12) },
{ "TLABStats", JDK_Version::jdk(12), JDK_Version::undefined(), JDK_Version::undefined() },
// -------------- Obsolete Flags - sorted by expired_in --------------
{ "CheckAssertionStatusDirectives",JDK_Version::undefined(), JDK_Version::jdk(11), JDK_Version::jdk(12) },
@ -3850,6 +3851,10 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) {
UNSUPPORTED_OPTION(UseLargePages);
#endif
#if defined(AIX)
UNSUPPORTED_OPTION(AllocateHeapAt);
#endif
ArgumentsExt::report_unsupported_options();
#ifndef PRODUCT

View File

@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "jfr/jfrEvents.hpp"
#include "jfr/support/jfrThreadId.hpp"
#include "logging/log.hpp"

View File

@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderDataGraph.inline.hpp"
#include "code/compiledIC.hpp"
#include "code/nmethod.hpp"
#include "code/scopeDesc.hpp"

View File

@ -26,6 +26,7 @@
#include "jvm.h"
#include "aot/aotLoader.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"

View File

@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderDataGraph.inline.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
#include "gc/shared/collectedHeap.inline.hpp"

View File

@ -110,7 +110,7 @@ static int Knob_Poverty = 1000;
static int Knob_FixedSpin = 0;
static int Knob_PreSpin = 10; // 20-100 likely better
static volatile int InitDone = 0;
DEBUG_ONLY(static volatile bool InitDone = false;)
// -----------------------------------------------------------------------------
// Theory of operations -- Monitors lists, thread residency, etc:
@ -428,7 +428,7 @@ void ObjectMonitor::EnterI(TRAPS) {
return;
}
DeferredInitialize();
assert(InitDone, "Unexpectedly not initialized");
// We try one round of spinning *before* enqueueing Self.
//
@ -1102,7 +1102,7 @@ intptr_t ObjectMonitor::complete_exit(TRAPS) {
assert(Self->is_Java_thread(), "Must be Java thread!");
JavaThread *jt = (JavaThread *)THREAD;
DeferredInitialize();
assert(InitDone, "Unexpectedly not initialized");
if (THREAD != _owner) {
if (THREAD->is_lock_owned ((address)_owner)) {
@ -1186,7 +1186,7 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
assert(Self->is_Java_thread(), "Must be Java thread!");
JavaThread *jt = (JavaThread *)THREAD;
DeferredInitialize();
assert(InitDone, "Unexpectedly not initialized");
// Throw IMSX or IEX.
CHECK_OWNER();
@ -1888,9 +1888,14 @@ PerfLongVariable * ObjectMonitor::_sync_MonExtant = NULL;
// be protected - like so many things - by the MonitorCache_lock.
void ObjectMonitor::Initialize() {
static int InitializationCompleted = 0;
assert(InitializationCompleted == 0, "invariant");
InitializationCompleted = 1;
assert(!InitDone, "invariant");
if (!os::is_MP()) {
Knob_SpinLimit = 0;
Knob_PreSpin = 0;
Knob_FixedSpin = -1;
}
if (UsePerfData) {
EXCEPTION_MARK;
#define NEWPERFCOUNTER(n) \
@ -1913,26 +1918,6 @@ void ObjectMonitor::Initialize() {
#undef NEWPERFCOUNTER
#undef NEWPERFVARIABLE
}
DEBUG_ONLY(InitDone = true;)
}
void ObjectMonitor::DeferredInitialize() {
if (InitDone > 0) return;
if (Atomic::cmpxchg (-1, &InitDone, 0) != 0) {
while (InitDone != 1) /* empty */;
return;
}
// One-shot global initialization ...
// The initialization is idempotent, so we don't need locks.
// In the future consider doing this via os::init_2().
if (!os::is_MP()) {
Knob_SpinLimit = 0;
Knob_PreSpin = 0;
Knob_FixedSpin = -1;
}
OrderAccess::fence();
InitDone = 1;
}

View File

@ -302,7 +302,6 @@ class ObjectMonitor {
private:
void AddWaiter(ObjectWaiter * waiter);
static void DeferredInitialize();
void INotify(Thread * Self);
ObjectWaiter * DequeueWaiter();
void DequeueSpecificWaiter(ObjectWaiter * waiter);

View File

@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderDataGraph.inline.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"

View File

@ -29,6 +29,7 @@
#include "ci/ciObjArrayKlass.hpp"
#include "ci/ciSymbol.hpp"
#include "classfile/compactHashtable.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/stringTable.hpp"

View File

@ -220,6 +220,8 @@ const char* Abstract_VM_Version::internal_vm_info_string() {
#define HOTSPOT_BUILD_COMPILER "MS VC++ 14.0 (VS2015)"
#elif _MSC_VER == 1912
#define HOTSPOT_BUILD_COMPILER "MS VC++ 15.5 (VS2017)"
#elif _MSC_VER == 1913
#define HOTSPOT_BUILD_COMPILER "MS VC++ 15.6 (VS2017)"
#else
#define HOTSPOT_BUILD_COMPILER "unknown MS VC++:" XSTR(_MSC_VER)
#endif

View File

@ -24,6 +24,8 @@
#include "precompiled.hpp"
#include "jvm.h"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"

View File

@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderDataGraph.inline.hpp"
#include "memory/allocation.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/thread.inline.hpp"

View File

@ -28,6 +28,7 @@ package java.util;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.util.ArraysSupport;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.concurrent.ForkJoinPool;
import java.util.function.BinaryOperator;
@ -4288,21 +4289,41 @@ public class Arrays {
// Misc
/**
* Returns a fixed-size list backed by the specified array. (Changes to
* the returned list "write through" to the array.) This method acts
* as bridge between array-based and collection-based APIs, in
* combination with {@link Collection#toArray}. The returned list is
* serializable and implements {@link RandomAccess}.
* Returns a fixed-size list backed by the specified array. Changes made to
* the array will be visible in the returned list, and changes made to the
* list will be visible in the array. The returned list is
* {@link Serializable} and implements {@link RandomAccess}.
*
* <p>The returned list implements the optional {@code Collection} methods, except
* those that would change the size of the returned list. Those methods leave
* the list unchanged and throw {@link UnsupportedOperationException}.
*
* @apiNote
* This method acts as bridge between array-based and collection-based
* APIs, in combination with {@link Collection#toArray}.
*
* <p>This method provides a way to wrap an existing array:
* <pre>{@code
* Integer[] numbers = ...
* ...
* List<Integer> values = Arrays.asList(numbers);
* }</pre>
*
* <p>This method also provides a convenient way to create a fixed-size
* list initialized to contain several elements:
* <pre>
* List&lt;String&gt; stooges = Arrays.asList("Larry", "Moe", "Curly");
* </pre>
* <pre>{@code
* List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
* }</pre>
*
* <p><em>The list returned by this method is modifiable.</em>
* To create an unmodifiable list, use
* {@link Collections#unmodifiableList Collections.unmodifiableList}
* or <a href="List.html#unmodifiable">Unmodifiable Lists</a>.
*
* @param <T> the class of the objects in the array
* @param a the array by which the list will be backed
* @return a list view of the specified array
* @throws NullPointerException if the specified array is {@code null}
*/
@SafeVarargs
@SuppressWarnings("varargs")

View File

@ -957,17 +957,17 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
@SuppressWarnings("serial")
static final class UniExceptionally<T> extends UniCompletion<T,T> {
Function<? super Throwable, ? extends T> fn;
UniExceptionally(CompletableFuture<T> dep, CompletableFuture<T> src,
UniExceptionally(Executor executor,
CompletableFuture<T> dep, CompletableFuture<T> src,
Function<? super Throwable, ? extends T> fn) {
super(null, dep, src); this.fn = fn;
super(executor, dep, src); this.fn = fn;
}
final CompletableFuture<T> tryFire(int mode) { // never ASYNC
// assert mode != ASYNC;
final CompletableFuture<T> tryFire(int mode) {
CompletableFuture<T> d; CompletableFuture<T> a;
Object r; Function<? super Throwable, ? extends T> f;
if ((d = dep) == null || (f = fn) == null
|| (a = src) == null || (r = a.result) == null
|| !d.uniExceptionally(r, f, this))
|| !d.uniExceptionally(r, f, mode > 0 ? null : this))
return null;
dep = null; src = null; fn = null;
return d.postFire(a, mode);
@ -980,11 +980,11 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
Throwable x;
if (result == null) {
try {
if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) {
if (c != null && !c.claim())
return false;
if (c != null && !c.claim())
return false;
if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
completeValue(f.apply(x));
} else
else
internalComplete(r);
} catch (Throwable ex) {
completeThrowable(ex);
@ -994,14 +994,88 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
}
private CompletableFuture<T> uniExceptionallyStage(
Function<Throwable, ? extends T> f) {
Executor e, Function<Throwable, ? extends T> f) {
if (f == null) throw new NullPointerException();
CompletableFuture<T> d = newIncompleteFuture();
Object r;
if ((r = result) == null)
unipush(new UniExceptionally<T>(d, this, f));
else
unipush(new UniExceptionally<T>(e, d, this, f));
else if (e == null)
d.uniExceptionally(r, f, null);
else {
try {
e.execute(new UniExceptionally<T>(null, d, this, f));
} catch (Throwable ex) {
d.result = encodeThrowable(ex);
}
}
return d;
}
@SuppressWarnings("serial")
static final class UniComposeExceptionally<T> extends UniCompletion<T,T> {
Function<Throwable, ? extends CompletionStage<T>> fn;
UniComposeExceptionally(Executor executor, CompletableFuture<T> dep,
CompletableFuture<T> src,
Function<Throwable, ? extends CompletionStage<T>> fn) {
super(executor, dep, src); this.fn = fn;
}
final CompletableFuture<T> tryFire(int mode) {
CompletableFuture<T> d; CompletableFuture<T> a;
Function<Throwable, ? extends CompletionStage<T>> f;
Object r; Throwable x;
if ((d = dep) == null || (f = fn) == null
|| (a = src) == null || (r = a.result) == null)
return null;
if (d.result == null) {
if ((r instanceof AltResult) &&
(x = ((AltResult)r).ex) != null) {
try {
if (mode <= 0 && !claim())
return null;
CompletableFuture<T> g = f.apply(x).toCompletableFuture();
if ((r = g.result) != null)
d.completeRelay(r);
else {
g.unipush(new UniRelay<T,T>(d, g));
if (d.result == null)
return null;
}
} catch (Throwable ex) {
d.completeThrowable(ex);
}
}
else
d.internalComplete(r);
}
dep = null; src = null; fn = null;
return d.postFire(a, mode);
}
}
private CompletableFuture<T> uniComposeExceptionallyStage(
Executor e, Function<Throwable, ? extends CompletionStage<T>> f) {
if (f == null) throw new NullPointerException();
CompletableFuture<T> d = newIncompleteFuture();
Object r, s; Throwable x;
if ((r = result) == null)
unipush(new UniComposeExceptionally<T>(e, d, this, f));
else if (!(r instanceof AltResult) || (x = ((AltResult)r).ex) == null)
d.internalComplete(r);
else
try {
if (e != null)
e.execute(new UniComposeExceptionally<T>(null, d, this, f));
else {
CompletableFuture<T> g = f.apply(x).toCompletableFuture();
if ((s = g.result) != null)
d.result = encodeRelay(s);
else
g.unipush(new UniRelay<T,T>(d, g));
}
} catch (Throwable ex) {
d.result = encodeThrowable(ex);
}
return d;
}
@ -1093,7 +1167,7 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
Object r, s; Throwable x;
if ((r = result) == null)
unipush(new UniCompose<T,V>(e, d, this, f));
else if (e == null) {
else {
if (r instanceof AltResult) {
if ((x = ((AltResult)r).ex) != null) {
d.result = encodeThrowable(x, r);
@ -1102,23 +1176,20 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
r = null;
}
try {
@SuppressWarnings("unchecked") T t = (T) r;
CompletableFuture<V> g = f.apply(t).toCompletableFuture();
if ((s = g.result) != null)
d.result = encodeRelay(s);
if (e != null)
e.execute(new UniCompose<T,V>(null, d, this, f));
else {
g.unipush(new UniRelay<V,V>(d, g));
@SuppressWarnings("unchecked") T t = (T) r;
CompletableFuture<V> g = f.apply(t).toCompletableFuture();
if ((s = g.result) != null)
d.result = encodeRelay(s);
else
g.unipush(new UniRelay<V,V>(d, g));
}
} catch (Throwable ex) {
d.result = encodeThrowable(ex);
}
}
else
try {
e.execute(new UniCompose<T,V>(null, d, this, f));
} catch (Throwable ex) {
d.result = encodeThrowable(ex);
}
return d;
}
@ -1898,7 +1969,7 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
* Creates a new complete CompletableFuture with given encoded result.
*/
CompletableFuture(Object r) {
this.result = r;
RESULT.setRelease(this, r);
}
/**
@ -2285,28 +2356,36 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
return this;
}
// not in interface CompletionStage
/**
* Returns a new CompletableFuture that is completed when this
* CompletableFuture completes, with the result of the given
* function of the exception triggering this CompletableFuture's
* completion when it completes exceptionally; otherwise, if this
* CompletableFuture completes normally, then the returned
* CompletableFuture also completes normally with the same value.
* Note: More flexible versions of this functionality are
* available using methods {@code whenComplete} and {@code handle}.
*
* @param fn the function to use to compute the value of the
* returned CompletableFuture if this CompletableFuture completed
* exceptionally
* @return the new CompletableFuture
*/
public CompletableFuture<T> exceptionally(
Function<Throwable, ? extends T> fn) {
return uniExceptionallyStage(fn);
return uniExceptionallyStage(null, fn);
}
public CompletableFuture<T> exceptionallyAsync(
Function<Throwable, ? extends T> fn) {
return uniExceptionallyStage(defaultExecutor(), fn);
}
public CompletableFuture<T> exceptionallyAsync(
Function<Throwable, ? extends T> fn, Executor executor) {
return uniExceptionallyStage(screenExecutor(executor), fn);
}
public CompletableFuture<T> exceptionallyCompose(
Function<Throwable, ? extends CompletionStage<T>> fn) {
return uniComposeExceptionallyStage(null, fn);
}
public CompletableFuture<T> exceptionallyComposeAsync(
Function<Throwable, ? extends CompletionStage<T>> fn) {
return uniComposeExceptionallyStage(defaultExecutor(), fn);
}
public CompletableFuture<T> exceptionallyComposeAsync(
Function<Throwable, ? extends CompletionStage<T>> fn,
Executor executor) {
return uniComposeExceptionallyStage(screenExecutor(executor), fn);
}
/* ------------- Arbitrary-arity constructions -------------- */

View File

@ -850,6 +850,130 @@ public interface CompletionStage<T> {
public CompletionStage<T> exceptionally
(Function<Throwable, ? extends T> fn);
/**
* Returns a new CompletionStage that, when this stage completes
* exceptionally, is executed with this stage's exception as the
* argument to the supplied function, using this stage's default
* asynchronous execution facility. Otherwise, if this stage
* completes normally, then the returned stage also completes
* normally with the same value.
*
* @implSpec The default implementation invokes {@link #handle},
* relaying to {@link #handleAsync} on exception, then {@link
* #thenCompose} for result.
*
* @param fn the function to use to compute the value of the
* returned CompletionStage if this CompletionStage completed
* exceptionally
* @return the new CompletionStage
* @since 12
*/
public default CompletionStage<T> exceptionallyAsync
(Function<Throwable, ? extends T> fn) {
return handle((r, ex) -> (ex == null)
? this
: this.<T>handleAsync((r1, ex1) -> fn.apply(ex1)))
.thenCompose(Function.identity());
}
/**
* Returns a new CompletionStage that, when this stage completes
* exceptionally, is executed with this stage's exception as the
* argument to the supplied function, using the supplied Executor.
* Otherwise, if this stage completes normally, then the returned
* stage also completes normally with the same value.
*
* @implSpec The default implementation invokes {@link #handle},
* relaying to {@link #handleAsync} on exception, then {@link
* #thenCompose} for result.
*
* @param fn the function to use to compute the value of the
* returned CompletionStage if this CompletionStage completed
* exceptionally
* @param executor the executor to use for asynchronous execution
* @return the new CompletionStage
* @since 12
*/
public default CompletionStage<T> exceptionallyAsync
(Function<Throwable, ? extends T> fn, Executor executor) {
return handle((r, ex) -> (ex == null)
? this
: this.<T>handleAsync((r1, ex1) -> fn.apply(ex1), executor))
.thenCompose(Function.identity());
}
/**
* Returns a new CompletionStage that, when this stage completes
* exceptionally, is composed using the results of the supplied
* function applied to this stage's exception.
*
* @implSpec The default implementation invokes {@link #handle},
* invoking the given function on exception, then {@link
* #thenCompose} for result.
*
* @param fn the function to use to compute the returned
* CompletionStage if this CompletionStage completed exceptionally
* @return the new CompletionStage
* @since 12
*/
public default CompletionStage<T> exceptionallyCompose
(Function<Throwable, ? extends CompletionStage<T>> fn) {
return handle((r, ex) -> (ex == null)
? this
: fn.apply(ex))
.thenCompose(Function.identity());
}
/**
* Returns a new CompletionStage that, when this stage completes
* exceptionally, is composed using the results of the supplied
* function applied to this stage's exception, using this stage's
* default asynchronous execution facility.
*
* @implSpec The default implementation invokes {@link #handle},
* relaying to {@link #handleAsync} on exception, then {@link
* #thenCompose} for result.
*
* @param fn the function to use to compute the returned
* CompletionStage if this CompletionStage completed exceptionally
* @return the new CompletionStage
* @since 12
*/
public default CompletionStage<T> exceptionallyComposeAsync
(Function<Throwable, ? extends CompletionStage<T>> fn) {
return handle((r, ex) -> (ex == null)
? this
: this.handleAsync((r1, ex1) -> fn.apply(ex1))
.thenCompose(Function.identity()))
.thenCompose(Function.identity());
}
/**
* Returns a new CompletionStage that, when this stage completes
* exceptionally, is composed using the results of the supplied
* function applied to this stage's exception, using the
* supplied Executor.
*
* @implSpec The default implementation invokes {@link #handle},
* relaying to {@link #handleAsync} on exception, then {@link
* #thenCompose} for result.
*
* @param fn the function to use to compute the returned
* CompletionStage if this CompletionStage completed exceptionally
* @param executor the executor to use for asynchronous execution
* @return the new CompletionStage
* @since 12
*/
public default CompletionStage<T> exceptionallyComposeAsync
(Function<Throwable, ? extends CompletionStage<T>> fn,
Executor executor) {
return handle((r, ex) -> (ex == null)
? this
: this.handleAsync((r1, ex1) -> fn.apply(ex1), executor)
.thenCompose(Function.identity()))
.thenCompose(Function.identity());
}
/**
* Returns a {@link CompletableFuture} maintaining the same
* completion properties as this stage. If this stage is already a

View File

@ -234,7 +234,6 @@ module java.base {
jdk.jconsole,
java.net.http;
exports sun.net.www to
java.desktop,
java.net.http,
jdk.jartool;
exports sun.net.www.protocol.http to

View File

@ -140,10 +140,6 @@ grant codeBase "jrt:/jdk.crypto.cryptoki" {
permission java.io.FilePermission "<<ALL FILES>>", "read";
};
grant codeBase "jrt:/jdk.desktop" {
permission java.lang.RuntimePermission "accessClassInPackage.com.sun.awt";
};
grant codeBase "jrt:/jdk.dynalink" {
permission java.security.AllPermission;
};

View File

@ -263,6 +263,8 @@ static char* nextToken(__ctx_args *pctx) {
}
JLI_List_addSubstring(pctx->parts, anchor, nextc - anchor);
pctx->state = IN_ESCAPE;
// anchor after backslash character
anchor = nextc + 1;
break;
case '\'':
case '"':

View File

@ -170,6 +170,10 @@ getJavaIDFromLangID(LANGID langID)
return NULL;
}
for (index = 0; index < 5; index++) {
elems[index] = NULL;
}
if (SetupI18nProps(MAKELCID(langID, SORT_DEFAULT),
&(elems[0]), &(elems[1]), &(elems[2]), &(elems[3]), &(elems[4]))) {
@ -183,15 +187,17 @@ getJavaIDFromLangID(LANGID langID)
strcat(ret, elems[index]);
}
}
for (index = 0; index < 5; index++) {
free(elems[index]);
}
} else {
free(ret);
ret = NULL;
}
for (index = 0; index < 5; index++) {
if (elems[index] != NULL) {
free(elems[index]);
}
}
return ret;
}

View File

@ -46,6 +46,7 @@ class _AppMenuBarHandler {
private static native void nativeSetMenuState(final int menu, final boolean visible, final boolean enabled);
private static native void nativeSetDefaultMenuBar(final long menuBarPeer);
private static native void nativeActivateDefaultMenuBar(final long menuBarPeer);
static final _AppMenuBarHandler instance = new _AppMenuBarHandler();
static _AppMenuBarHandler getInstance() {
@ -78,26 +79,18 @@ class _AppMenuBarHandler {
void setDefaultMenuBar(final JMenuBar menuBar) {
installDefaultMenuBar(menuBar);
if (menuBar == null) {
return;
}
}
static boolean isMenuBarActivationNeeded() {
// scan the current frames, and see if any are foreground
final Frame[] frames = Frame.getFrames();
for (final Frame frame : frames) {
if (frame.isVisible() && !isFrameMinimized(frame)) {
return;
return false;
}
}
// if we have no foreground frames, then we have to "kick" the menubar
final JFrame pingFrame = new JFrame();
pingFrame.getRootPane().putClientProperty("Window.alpha", Float.valueOf(0.0f));
pingFrame.setUndecorated(true);
pingFrame.setVisible(true);
pingFrame.toFront();
pingFrame.setVisible(false);
pingFrame.dispose();
return true;
}
static boolean isFrameMinimized(final Frame frame) {
@ -150,6 +143,11 @@ class _AppMenuBarHandler {
// grab the pointer to the CMenuBar, and retain it in native
((CMenuBar) peer).execute(_AppMenuBarHandler::nativeSetDefaultMenuBar);
// if there is no currently active frame, install the default menu bar in the application main menu
if (isMenuBarActivationNeeded()) {
((CMenuBar) peer).execute(_AppMenuBarHandler::nativeActivateDefaultMenuBar);
}
}
void setAboutMenuItemVisible(final boolean present) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2018, 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
@ -506,12 +506,6 @@ public final class CStrike extends PhysicalStrike {
private SparseBitShiftingTwoLayerArray secondLayerCache;
private HashMap<Integer, Float> generalCache;
// Empty non private constructor was added because access to this
// class shouldn't be emulated by a synthetic accessor method.
GlyphAdvanceCache() {
super();
}
public synchronized float get(final int index) {
if (index < 0) {
if (-index < SECOND_LAYER_SIZE) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2018, 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
@ -81,12 +81,6 @@ final class LWButtonPeer extends LWComponentPeer<Button, JButton>
@SuppressWarnings("serial")// Safe: outer class is non-serializable.
private final class JButtonDelegate extends JButton {
// Empty non private constructor was added because access to this
// class shouldn't be emulated by a synthetic accessor method.
JButtonDelegate() {
super();
}
@Override
public boolean hasFocus() {
return getTarget().hasFocus();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2018, 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
@ -135,12 +135,6 @@ final class LWChoicePeer extends LWComponentPeer<Choice, JComboBox<String>>
@SuppressWarnings("serial")// Safe: outer class is non-serializable.
private final class JComboBoxDelegate extends JComboBox<String> {
// Empty non private constructor was added because access to this
// class shouldn't be emulated by a synthetic accessor method.
JComboBoxDelegate() {
super();
}
@Override
public boolean hasFocus() {
return getTarget().hasFocus();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2018, 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
@ -159,12 +159,6 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
enableEvents(0xFFFFFFFF);
}
// Empty non private constructor was added because access to this
// class shouldn't be emulated by a synthetic accessor method.
DelegateContainer() {
super();
}
@Override
public boolean isLightweight() {
return false;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2018, 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
@ -219,12 +219,6 @@ final class LWTextAreaPeer
private final class JTextAreaDelegate extends JTextArea {
// Empty non private constructor was added because access to this
// class shouldn't be emulated by a synthetic accessor method.
JTextAreaDelegate() {
super();
}
@Override
public void replaceSelection(String content) {
getDocument().removeDocumentListener(LWTextAreaPeer.this);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2018, 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
@ -122,12 +122,6 @@ final class LWTextFieldPeer
@SuppressWarnings("serial")// Safe: outer class is non-serializable.
private final class JPasswordFieldDelegate extends JPasswordField {
// Empty non private constructor was added because access to this
// class shouldn't be emulated by a synthetic accessor method.
JPasswordFieldDelegate() {
super();
}
@Override
public void replaceSelection(String content) {
getDocument().removeDocumentListener(LWTextFieldPeer.this);

View File

@ -165,8 +165,6 @@ public class CEmbeddedFrame extends EmbeddedFrame {
: this;
}
}
// ignore focus "lost" native request as it may mistakenly
// deactivate active window (see 8001161)
if (globalFocusedWindow == this) {
responder.handleWindowFocusEvent(parentWindowActive, null);
}
@ -181,4 +179,19 @@ public class CEmbeddedFrame extends EmbeddedFrame {
// another window.
return globalFocusedWindow != null ? !globalFocusedWindow.isParentWindowActive() : true;
}
@Override
public void synthesizeWindowActivation(boolean doActivate) {
if (isParentWindowActive() != doActivate) {
handleWindowFocusEvent(doActivate);
}
}
public static void updateGlobalFocusedWindow(CEmbeddedFrame newGlobalFocusedWindow) {
synchronized (classLock) {
if (newGlobalFocusedWindow.isParentWindowActive()) {
globalFocusedWindow = newGlobalFocusedWindow;
}
}
}
}

View File

@ -147,6 +147,8 @@ public class CPlatformEmbeddedFrame implements PlatformWindow {
@Override
public boolean requestWindowFocus() {
CEmbeddedFrame.updateGlobalFocusedWindow(target);
target.synthesizeWindowActivation(true);
return true;
}

View File

@ -1205,17 +1205,27 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
}
private void orderAboveSiblings() {
// Recursively pop up the windows from the very bottom, (i.e. root owner) so that
// the windows are ordered above their nearest owner; ancestors of the window,
// which is going to become 'main window', are placed above their siblings.
CPlatformWindow rootOwner = getRootOwner();
if (rootOwner.isVisible() && !rootOwner.isIconified()) {
rootOwner.execute(CWrapper.NSWindow::orderFront);
}
// Do not order child windows of iconified owner.
if (!rootOwner.isIconified()) {
final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor();
orderAboveSiblingsImpl(windowAccessor.getOwnedWindows(rootOwner.target));
Window[] windows = windowAccessor.getOwnedWindows(rootOwner.target);
// No need to order windows if it doesn't own other windows and hence return
if (windows.length == 0) {
return;
}
// Recursively pop up the windows from the very bottom, (i.e. root owner) so that
// the windows are ordered above their nearest owner; ancestors of the window,
// which is going to become 'main window', are placed above their siblings.
if (rootOwner.isVisible()) {
rootOwner.execute(CWrapper.NSWindow::orderFront);
}
// Order child windows.
orderAboveSiblingsImpl(windows);
}
}
@ -1276,6 +1286,21 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
}
}
private Window getOwnerFrameOrDialog(Window window) {
Window owner = window.getOwner();
while (owner != null && !(owner instanceof Frame || owner instanceof Dialog)) {
owner = owner.getOwner();
}
return owner;
}
private boolean isSimpleWindowOwnedByEmbeddedFrame() {
if (peer != null && peer.isSimpleWindow()) {
return (getOwnerFrameOrDialog(target) instanceof CEmbeddedFrame);
}
return false;
}
// ----------------------------------------------------------------------
// NATIVE CALLBACKS
// ----------------------------------------------------------------------

View File

@ -537,10 +537,14 @@ static BOOL shouldUsePressAndHold() {
}
-(BOOL) isCodePointInUnicodeBlockNeedingIMEvent: (unichar) codePoint {
if (((codePoint >= 0x3000) && (codePoint <= 0x303F)) ||
if ((codePoint == 0x0024) || (codePoint == 0x00A3) ||
(codePoint == 0x00A5) ||
((codePoint >= 0x20A3) && (codePoint <= 0x20BF)) ||
((codePoint >= 0x3000) && (codePoint <= 0x303F)) ||
((codePoint >= 0xFF00) && (codePoint <= 0xFFEF))) {
// Code point is in 'CJK Symbols and Punctuation' or
// 'Halfwidth and Fullwidth Forms' Unicode block.
// 'Halfwidth and Fullwidth Forms' Unicode block or
// currency symbols unicode
return YES;
}
return NO;

View File

@ -477,6 +477,21 @@ AWT_ASSERT_APPKIT_THREAD;
return isBlocked;
}
// Test whether window is simple window and owned by embedded frame
- (BOOL) isSimpleWindowOwnedByEmbeddedFrame {
BOOL isSimpleWindowOwnedByEmbeddedFrame = NO;
JNIEnv *env = [ThreadUtilities getJNIEnv];
jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
if (platformWindow != NULL) {
static JNF_MEMBER_CACHE(jm_isBlocked, jc_CPlatformWindow, "isSimpleWindowOwnedByEmbeddedFrame", "()Z");
isSimpleWindowOwnedByEmbeddedFrame = JNFCallBooleanMethod(env, platformWindow, jm_isBlocked) == JNI_TRUE ? YES : NO;
(*env)->DeleteLocalRef(env, platformWindow);
}
return isSimpleWindowOwnedByEmbeddedFrame;
}
// Tests whether the corresponding Java platform window is visible or not
+ (BOOL) isJavaPlatformWindowVisible:(NSWindow *)window {
BOOL isVisible = NO;
@ -543,7 +558,7 @@ AWT_ASSERT_APPKIT_THREAD;
// NSWindow overrides
- (BOOL) canBecomeKeyWindow {
AWT_ASSERT_APPKIT_THREAD;
return self.isEnabled && IS(self.styleBits, SHOULD_BECOME_KEY);
return self.isEnabled && (IS(self.styleBits, SHOULD_BECOME_KEY) || [self isSimpleWindowOwnedByEmbeddedFrame]);
}
- (BOOL) canBecomeMainWindow {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2018, 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
@ -35,10 +35,10 @@
#import <JavaNativeFoundation/JavaNativeFoundation.h>
#import "CPopupMenu.h"
#import "CMenuBar.h"
#import "ThreadUtilities.h"
#import "NSApplicationAWT.h"
#pragma mark App Menu helpers
// The following is a AWT convention?
@ -201,11 +201,11 @@ AWT_ASSERT_APPKIT_THREAD;
self.fPreferencesMenu = (NSMenuItem*)[appMenu itemWithTag:PREFERENCES_TAG];
self.fAboutMenu = (NSMenuItem*)[appMenu itemAtIndex:0];
NSDockTile *dockTile = [NSApp dockTile];
self.fProgressIndicator = [[NSProgressIndicator alloc]
initWithFrame:NSMakeRect(3.f, 0.f, dockTile.size.width - 6.f, 20.f)];
[fProgressIndicator setStyle:NSProgressIndicatorBarStyle];
[fProgressIndicator setIndeterminate:NO];
[[dockTile contentView] addSubview:fProgressIndicator];
@ -824,3 +824,23 @@ JNF_COCOA_ENTER(env);
JNF_COCOA_EXIT(env);
}
/*
* Class: com_apple_eawt__AppMenuBarHandler
* Method: nativeActivateDefaultMenuBar
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMenuBarHandler_nativeActivateDefaultMenuBar
(JNIEnv *env, jclass clz, jlong cMenuBarPtr)
{
JNF_COCOA_ENTER(env);
CMenuBar *menu = (CMenuBar *)jlong_to_ptr(cMenuBarPtr);
[ThreadUtilities performOnMainThreadWaiting:NO block:^(){
if (menu) {
[CMenuBar activate:menu modallyDisabled:NO];
}
}];
JNF_COCOA_EXIT(env);
}

View File

@ -1,172 +0,0 @@
/*
* Copyright (c) 2008, 2018, 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 com.sun.awt;
import java.awt.*;
import java.awt.geom.*;
import sun.awt.AWTAccessor;
/**
* Security Warning control interface.
*
* This class provides a couple of methods that help a developer relocate
* the AWT security warning to an appropriate position relative to the current
* window size. A "top-level window" is an instance of the {@code Window}
* class (or its descendant, such as {@code JFrame}). The security warning
* is applied to all windows created by an untrusted code. All such windows
* have a non-null "warning string" (see {@link Window#getWarningString()}).
* <p>
* <b>WARNING</b>: This class is an implementation detail and only meant
* for limited use outside of the core platform. This API may change
* drastically between update release, and it may even be
* removed or be moved to some other packages or classes.
*
* @deprecated This class is deprecated, no replacement.
*/
@Deprecated(since = "11", forRemoval = true)
public final class SecurityWarning {
/**
* The SecurityWarning class should not be instantiated
*/
private SecurityWarning() {
}
/**
* Gets the size of the security warning.
*
* The returned value is not valid until the peer has been created. Before
* invoking this method a developer must call the {@link Window#pack()},
* {@link Window#setVisible}, or some other method that creates the peer.
*
* @param window the window to get the security warning size for
*
* @throws NullPointerException if the window argument is null
* @throws IllegalArgumentException if the window is trusted (i.e.
* the {@code getWarningString()} returns null)
*/
public static Dimension getSize(Window window) {
if (window == null) {
throw new NullPointerException(
"The window argument should not be null.");
}
if (window.getWarningString() == null) {
throw new IllegalArgumentException(
"The window must have a non-null warning string.");
}
// We don't check for a non-null peer since it may be destroyed
// after assigning a valid value to the security warning size.
return AWTAccessor.getWindowAccessor().getSecurityWarningSize(window);
}
/**
* Sets the position of the security warning.
* <p>
* The {@code alignmentX} and {@code alignmentY} arguments specify the
* origin of the coordinate system used to calculate the position of the
* security warning. The values must be in the range [0.0f...1.0f]. The
* {@code 0.0f} value represents the left (top) edge of the rectangular
* bounds of the window. The {@code 1.0f} value represents the right
* (bottom) edge of the bounds. Whenever the size of the window changes,
* the origin of the coordinate system gets relocated accordingly. For
* convenience a developer may use the {@code Component.*_ALIGNMENT}
* constants to pass predefined values for these arguments.
* <p>
* The {@code point} argument specifies the location of the security
* warning in the coordinate system described above. If both {@code x} and
* {@code y} coordinates of the point are equal to zero, the warning will
* be located right in the origin of the coordinate system. On the other
* hand, if both {@code alignmentX} and {@code alignmentY} are equal to
* zero (i.e. the origin of the coordinate system is placed at the top-left
* corner of the window), then the {@code point} argument represents the
* absolute location of the security warning relative to the location of
* the window. The "absolute" in this case means that the position of the
* security warning is not effected by resizing of the window.
* <p>
* Note that the security warning management code guarantees that:
* <ul>
* <li>The security warning cannot be located farther than two pixels from
* the rectangular bounds of the window (see {@link Window#getBounds}), and
* <li>The security warning is always visible on the screen.
* </ul>
* If either of the conditions is violated, the calculated position of the
* security warning is adjusted by the system to meet both these
* conditions.
* <p>
* The default position of the security warning is in the upper-right
* corner of the window, two pixels to the right from the right edge. This
* corresponds to the following arguments passed to this method:
* <ul>
* <li>{@code alignmentX = Component.RIGHT_ALIGNMENT}
* <li>{@code alignmentY = Component.TOP_ALIGNMENT}
* <li>{@code point = (2, 0)}
* </ul>
*
* @param window the window to set the position of the security warning for
* @param alignmentX the horizontal origin of the coordinate system
* @param alignmentY the vertical origin of the coordinate system
* @param point the position of the security warning in the specified
* coordinate system
*
* @throws NullPointerException if the window argument is null
* @throws NullPointerException if the point argument is null
* @throws IllegalArgumentException if the window is trusted (i.e.
* the {@code getWarningString()} returns null
* @throws IllegalArgumentException if the alignmentX or alignmentY
* arguments are not within the range [0.0f ... 1.0f]
*/
public static void setPosition(Window window, Point2D point,
float alignmentX, float alignmentY)
{
if (window == null) {
throw new NullPointerException(
"The window argument should not be null.");
}
if (window.getWarningString() == null) {
throw new IllegalArgumentException(
"The window must have a non-null warning string.");
}
if (point == null) {
throw new NullPointerException(
"The point argument must not be null");
}
if (alignmentX < 0.0f || alignmentX > 1.0f) {
throw new IllegalArgumentException(
"alignmentX must be in the range [0.0f ... 1.0f].");
}
if (alignmentY < 0.0f || alignmentY > 1.0f) {
throw new IllegalArgumentException(
"alignmentY must be in the range [0.0f ... 1.0f].");
}
AWTAccessor.getWindowAccessor().setSecurityWarningPosition(window,
point, alignmentX, alignmentY);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2018, 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
@ -547,14 +547,15 @@ final class DirectAudioDevice extends AbstractMixer {
getEventDispatcher().addLineMonitor(this);
}
doIO = true;
// need to set Active and Started
// note: the current API always requires that
// Started and Active are set at the same time...
if (isSource && stoppedWritten) {
setStarted(true);
setActive(true);
synchronized(lock) {
doIO = true;
// need to set Active and Started
// note: the current API always requires that
// Started and Active are set at the same time...
if (isSource && stoppedWritten) {
setStarted(true);
setActive(true);
}
}
if (Printer.trace) Printer.trace("<< DirectDL: implStart() succeeded");
@ -582,10 +583,10 @@ final class DirectAudioDevice extends AbstractMixer {
// read/write thread, that's why isStartedRunning()
// cannot be used
doIO = false;
setActive(false);
setStarted(false);
lock.notifyAll();
}
setActive(false);
setStarted(false);
stoppedWritten = false;
if (Printer.trace) Printer.trace(" << DirectDL: implStop() succeeded");
@ -731,12 +732,14 @@ final class DirectAudioDevice extends AbstractMixer {
if ((long)off + (long)len > (long)b.length) {
throw new ArrayIndexOutOfBoundsException(b.length);
}
if (!isActive() && doIO) {
// this is not exactly correct... would be nicer
// if the native sub system sent a callback when IO really starts
setActive(true);
setStarted(true);
synchronized(lock) {
if (!isActive() && doIO) {
// this is not exactly correct... would be nicer
// if the native sub system sent a callback when IO really
// starts
setActive(true);
setStarted(true);
}
}
int written = 0;
while (!flushing) {
@ -957,11 +960,14 @@ final class DirectAudioDevice extends AbstractMixer {
if ((long)off + (long)len > (long)b.length) {
throw new ArrayIndexOutOfBoundsException(b.length);
}
if (!isActive() && doIO) {
// this is not exactly correct... would be nicer
// if the native sub system sent a callback when IO really starts
setActive(true);
setStarted(true);
synchronized(lock) {
if (!isActive() && doIO) {
// this is not exactly correct... would be nicer
// if the native sub system sent a callback when IO really
// starts
setActive(true);
setStarted(true);
}
}
int read = 0;
while (doIO && !flushing) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2018, 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
@ -169,18 +169,9 @@ public abstract class GraphicsEnvironment {
String nm = System.getProperty("java.awt.headless");
if (nm == null) {
/* No need to ask for DISPLAY when run in a browser */
if (System.getProperty("javaplugin.version") != null) {
headless = defaultHeadless = Boolean.FALSE;
} else {
String osName = System.getProperty("os.name");
if (osName.contains("OS X") && "sun.awt.HToolkit".equals(
System.getProperty("awt.toolkit")))
{
headless = defaultHeadless = Boolean.TRUE;
} else {
final String display = System.getenv("DISPLAY");
headless = defaultHeadless =
final String osName = System.getProperty("os.name");
final String display = System.getenv("DISPLAY");
headless = defaultHeadless =
("Linux".equals(osName) ||
"SunOS".equals(osName) ||
"FreeBSD".equals(osName) ||
@ -188,8 +179,6 @@ public abstract class GraphicsEnvironment {
"OpenBSD".equals(osName) ||
"AIX".equals(osName)) &&
(display == null || display.trim().isEmpty());
}
}
} else {
headless = Boolean.valueOf(nm);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 2018, 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
@ -394,16 +394,6 @@ public class Window extends Container implements Accessible {
private transient volatile int securityWarningWidth = 0;
private transient volatile int securityWarningHeight = 0;
/**
* These fields represent the desired location for the security
* warning if this window is untrusted.
* See com.sun.awt.SecurityWarning for more details.
*/
private transient double securityWarningPointX = 2.0;
private transient double securityWarningPointY = 0.0;
private transient float securityWarningAlignmentX = RIGHT_ALIGNMENT;
private transient float securityWarningAlignmentY = TOP_ALIGNMENT;
static {
/* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
@ -3127,10 +3117,6 @@ public class Window extends Container implements Accessible {
this.securityWarningWidth = 0;
this.securityWarningHeight = 0;
this.securityWarningPointX = 2.0;
this.securityWarningPointY = 0.0;
this.securityWarningAlignmentX = RIGHT_ALIGNMENT;
this.securityWarningAlignmentY = TOP_ALIGNMENT;
deserializeResources(s);
}
@ -4031,9 +4017,9 @@ public class Window extends Container implements Accessible {
private Point2D calculateSecurityWarningPosition(double x, double y,
double w, double h)
{
// The position according to the spec of SecurityWarning.setPosition()
double wx = x + w * securityWarningAlignmentX + securityWarningPointX;
double wy = y + h * securityWarningAlignmentY + securityWarningPointY;
// The desired location for the security warning
double wx = x + w * RIGHT_ALIGNMENT + 2.0;
double wy = y + h * TOP_ALIGNMENT + 0.0;
// First, make sure the warning is not too far from the window bounds
wx = Window.limit(wx,
@ -4068,33 +4054,12 @@ public class Window extends Container implements Accessible {
window.updateWindow();
}
public Dimension getSecurityWarningSize(Window window) {
return new Dimension(window.securityWarningWidth,
window.securityWarningHeight);
}
public void setSecurityWarningSize(Window window, int width, int height)
{
window.securityWarningWidth = width;
window.securityWarningHeight = height;
}
public void setSecurityWarningPosition(Window window,
Point2D point, float alignmentX, float alignmentY)
{
window.securityWarningPointX = point.getX();
window.securityWarningPointY = point.getY();
window.securityWarningAlignmentX = alignmentX;
window.securityWarningAlignmentY = alignmentY;
synchronized (window.getTreeLock()) {
WindowPeer peer = (WindowPeer) window.peer;
if (peer != null) {
peer.repositionSecurityWarning();
}
}
}
public Point2D calculateSecurityWarningPosition(Window window,
double x, double y, double w, double h)
{

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2018, 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
@ -1814,12 +1814,6 @@ public class RepaintManager
*/
private static final class DisplayChangedHandler implements
DisplayChangedListener {
// Empty non private constructor was added because access to this
// class shouldn't be generated by the compiler using synthetic
// accessor method
DisplayChangedHandler() {
}
public void displayChanged() {
scheduleDisplayChanges();
}

View File

@ -42,6 +42,8 @@ import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicHTML;
import jdk.internal.ref.CleanerFactory;
/**
* A class which implements an arbitrary border
* with the addition of a String title in a
@ -759,22 +761,19 @@ public class TitledBorder extends AbstractBorder
private void installPropertyChangeListeners() {
final WeakReference<TitledBorder> weakReference = new WeakReference<TitledBorder>(this);
final PropertyChangeListener listener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (weakReference.get() == null) {
UIManager.removePropertyChangeListener(this);
UIManager.getDefaults().removePropertyChangeListener(this);
} else {
String prop = evt.getPropertyName();
if ("lookAndFeel".equals(prop) || "LabelUI".equals(prop)) {
label.updateUI();
}
}
final PropertyChangeListener listener = evt -> {
TitledBorder tb = weakReference.get();
String prop = evt.getPropertyName();
if (tb != null && ("lookAndFeel".equals(prop) || "LabelUI".equals(prop))) {
tb.label.updateUI();
}
};
UIManager.addPropertyChangeListener(listener);
UIManager.getDefaults().addPropertyChangeListener(listener);
CleanerFactory.cleaner().register(this, () -> {
UIManager.removePropertyChangeListener(listener);
UIManager.getDefaults().removePropertyChangeListener(listener);
});
}
}

Some files were not shown because too many files have changed in this diff Show More