Merge
This commit is contained in:
commit
08e1f72237
1
.hgtags
1
.hgtags
@ -513,3 +513,4 @@ ef57958c7c511162da8d9a75f0b977f0f7ac464e jdk-12+7
|
||||
8f594f75e0547d4ca16649cb3501659e3155e81b jdk-12+10
|
||||
f0f5d23449d31f1b3580c8a73313918cafeaefd7 jdk-12+11
|
||||
15094d12a632f452a2064318a4e416d0c7a9ce0c jdk-12+12
|
||||
511a9946f83e3e3c7b9dbe1840367063fb39b4e1 jdk-12+13
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
697
src/hotspot/share/classfile/classLoaderDataGraph.cpp
Normal file
697
src/hotspot/share/classfile/classLoaderDataGraph.cpp
Normal 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
|
182
src/hotspot/share/classfile/classLoaderDataGraph.hpp
Normal file
182
src/hotspot/share/classfile/classLoaderDataGraph.hpp
Normal 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
|
82
src/hotspot/share/classfile/classLoaderDataGraph.inline.hpp
Normal file
82
src/hotspot/share/classfile/classLoaderDataGraph.inline.hpp
Normal 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
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/classLoaderDataGraph.hpp"
|
||||
#include "classfile/metadataOnStackMark.hpp"
|
||||
#include "classfile/stringTable.hpp"
|
||||
#include "code/codeCache.hpp"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/classLoaderDataGraph.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "classfile/stringTable.hpp"
|
||||
#include "classfile/symbolTable.hpp"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/classLoaderDataGraph.hpp"
|
||||
#include "classfile/metadataOnStackMark.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "code/codeCache.hpp"
|
||||
|
@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/classLoaderDataGraph.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "jvmtifiles/jvmtiEnv.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/classLoaderDataGraph.hpp"
|
||||
#include "classfile/javaClasses.inline.hpp"
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/classLoaderDataGraph.hpp"
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#include "jfr/support/jfrThreadId.hpp"
|
||||
#include "logging/log.hpp"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -302,7 +302,6 @@ class ObjectMonitor {
|
||||
|
||||
private:
|
||||
void AddWaiter(ObjectWaiter * waiter);
|
||||
static void DeferredInitialize();
|
||||
void INotify(Thread * Self);
|
||||
ObjectWaiter * DequeueWaiter();
|
||||
void DequeueSpecificWaiter(ObjectWaiter * waiter);
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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<String> 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")
|
||||
|
@ -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 -------------- */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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 '"':
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -147,6 +147,8 @@ public class CPlatformEmbeddedFrame implements PlatformWindow {
|
||||
|
||||
@Override
|
||||
public boolean requestWindowFocus() {
|
||||
CEmbeddedFrame.updateGlobalFocusedWindow(target);
|
||||
target.synthesizeWindowActivation(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
// ----------------------------------------------------------------------
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user