Merge
This commit is contained in:
commit
08e1f72237
1
.hgtags
1
.hgtags
@ -513,3 +513,4 @@ ef57958c7c511162da8d9a75f0b977f0f7ac464e jdk-12+7
|
|||||||
8f594f75e0547d4ca16649cb3501659e3155e81b jdk-12+10
|
8f594f75e0547d4ca16649cb3501659e3155e81b jdk-12+10
|
||||||
f0f5d23449d31f1b3580c8a73313918cafeaefd7 jdk-12+11
|
f0f5d23449d31f1b3580c8a73313918cafeaefd7 jdk-12+11
|
||||||
15094d12a632f452a2064318a4e416d0c7a9ce0c jdk-12+12
|
15094d12a632f452a2064318a4e416d0c7a9ce0c jdk-12+12
|
||||||
|
511a9946f83e3e3c7b9dbe1840367063fb39b4e1 jdk-12+13
|
||||||
|
@ -351,6 +351,11 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES],
|
|||||||
AC_MSG_RESULT([no])
|
AC_MSG_RESULT([no])
|
||||||
fi
|
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
|
# Turn on additional features based on other parts of configure
|
||||||
if test "x$INCLUDE_DTRACE" = "xtrue"; then
|
if test "x$INCLUDE_DTRACE" = "xtrue"; then
|
||||||
JVM_FEATURES="$JVM_FEATURES dtrace"
|
JVM_FEATURES="$JVM_FEATURES dtrace"
|
||||||
|
@ -840,7 +840,7 @@ var getJibProfilesDependencies = function (input, common) {
|
|||||||
linux_x64: "gcc7.3.0-OEL6.4+1.0",
|
linux_x64: "gcc7.3.0-OEL6.4+1.0",
|
||||||
macosx_x64: "Xcode9.4-MacOSX10.13+1.0",
|
macosx_x64: "Xcode9.4-MacOSX10.13+1.0",
|
||||||
solaris_x64: "SS12u4-Solaris11u1+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",
|
windows_x64: "VS2017-15.5.5+1.0",
|
||||||
linux_aarch64: (input.profile != null && input.profile.indexOf("arm64") >= 0
|
linux_aarch64: (input.profile != null && input.profile.indexOf("arm64") >= 0
|
||||||
? "gcc-linaro-aarch64-linux-gnu-4.8-2013.11_linux+1.0"
|
? "gcc-linaro-aarch64-linux-gnu-4.8-2013.11_linux+1.0"
|
||||||
|
@ -34,18 +34,19 @@
|
|||||||
# install in a separate temporary image.
|
# install in a separate temporary image.
|
||||||
#
|
#
|
||||||
# The Solaris Studio installation must contain at least these packages:
|
# The Solaris Studio installation must contain at least these packages:
|
||||||
# developer/developerstudio-126/backend 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.0.0 i--
|
#developer/developerstudio-126/c++ 12.6-1.0.2.0
|
||||||
# developer/developerstudio-126/cc 12.6-1.0.0.0 i--
|
#developer/developerstudio-126/cc 12.6-1.0.1.0
|
||||||
# developer/developerstudio-126/dbx (solarisstudio) 12.6-1.0.0.0 i--
|
#developer/developerstudio-126/dbx 12.6-1.0.0.1
|
||||||
# developer/developerstudio-126/library/c++-libs 12.6-1.0.0.0 i--
|
#developer/developerstudio-126/library/c++-libs 12.6-1.0.2.0
|
||||||
# developer/developerstudio-126/library/math-libs 12.6-1.0.0.0 i--
|
#developer/developerstudio-126/library/c-libs 12.6-1.0.0.1
|
||||||
# developer/developerstudio-126/library/c-libs 12.6-1.0.0.0 i--
|
#developer/developerstudio-126/library/f90-libs 12.6-1.0.0.1
|
||||||
# developer/developerstudio-126/library/studio-gccrt 12.6-1.0.0.0 i--
|
#developer/developerstudio-126/library/math-libs 12.6-1.0.0.1
|
||||||
# developer/developerstudio-126/studio-common 12.6-1.0.0.0 i--
|
#developer/developerstudio-126/library/studio-gccrt 12.6-1.0.0.1
|
||||||
# developer/developerstudio-126/studio-ja 12.6-1.0.0.0 i--
|
#developer/developerstudio-126/studio-common 12.6-1.0.0.1
|
||||||
# developer/developerstudio-126/studio-legal 12.6-1.0.0.0 i--
|
#developer/developerstudio-126/studio-ja 12.6-1.0.0.1
|
||||||
# developer/developerstudio-126/studio-zhCN 12.6-1.0.0.0 i--
|
#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
|
# erik.joelsson@oracle.com
|
||||||
|
|
||||||
@ -93,7 +94,7 @@ if [ ! -d $INSTALL_ROOT ]; then
|
|||||||
pkg -R $INSTALL_ROOT set-publisher -P -g ${PUBLISHER_URI} solaris
|
pkg -R $INSTALL_ROOT set-publisher -P -g ${PUBLISHER_URI} solaris
|
||||||
sudo pkg -R $INSTALL_ROOT install --accept entire@$SOLARIS_ENTIRE_VERSION \
|
sudo pkg -R $INSTALL_ROOT install --accept entire@$SOLARIS_ENTIRE_VERSION \
|
||||||
system/install developer/gnu-binutils system/library/mmheap system/picl \
|
system/install developer/gnu-binutils system/library/mmheap system/picl \
|
||||||
developer/assembler
|
developer/assembler system/library/freetype-2
|
||||||
else
|
else
|
||||||
echo "Skipping installing packages"
|
echo "Skipping installing packages"
|
||||||
fi
|
fi
|
||||||
|
@ -244,7 +244,7 @@ ifeq ($(OPENJDK_TARGET_OS), aix)
|
|||||||
EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
|
EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
|
||||||
EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
|
EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
|
||||||
OPTIMIZATION := HIGH, \
|
OPTIMIZATION := HIGH, \
|
||||||
CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS_JDKLIB) $(LIBJLI_CFLAGS) \
|
CFLAGS := $(STATIC_LIBRARY_FLAGS) $(CFLAGS_JDKLIB) $(LIBJLI_CFLAGS) \
|
||||||
$(addprefix -I, $(LIBJLI_SRC_DIRS)), \
|
$(addprefix -I, $(LIBJLI_SRC_DIRS)), \
|
||||||
ARFLAGS := $(ARFLAGS), \
|
ARFLAGS := $(ARFLAGS), \
|
||||||
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static))
|
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;
|
package java2d;
|
||||||
|
|
||||||
import java.awt.Color;
|
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;
|
package java2d;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
@ -870,8 +870,8 @@ void LIRGenerator::do_ArithmeticOp(ArithmeticOp* x) {
|
|||||||
case doubleTag: do_ArithmeticOp_FPU(x); return;
|
case doubleTag: do_ArithmeticOp_FPU(x); return;
|
||||||
case longTag: do_ArithmeticOp_Long(x); return;
|
case longTag: do_ArithmeticOp_Long(x); return;
|
||||||
case intTag: do_ArithmeticOp_Int(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) {
|
switch (code) {
|
||||||
case Bytecodes::_nofast_getfield: code = Bytecodes::_getfield; break;
|
case Bytecodes::_nofast_getfield: code = Bytecodes::_getfield; break;
|
||||||
case Bytecodes::_nofast_putfield: code = Bytecodes::_putfield; 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");
|
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()) {
|
if (UseAVX > 2 && !VM_Version::supports_avx512vl()) {
|
||||||
assert(tmp->is_valid(), "need temporary");
|
assert(tmp->is_valid(), "need temporary");
|
||||||
__ vpandn(dest->as_xmm_double_reg(), tmp->as_xmm_double_reg(), value->as_xmm_double_reg(), 2);
|
__ vpandn(dest->as_xmm_double_reg(), tmp->as_xmm_double_reg(), value->as_xmm_double_reg(), 2);
|
||||||
} else {
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
if (dest->as_xmm_double_reg() != value->as_xmm_double_reg()) {
|
if (dest->as_xmm_double_reg() != value->as_xmm_double_reg()) {
|
||||||
__ movdbl(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_BYTE: slow_case_addr = jni_GetByteField_addr(); break;
|
||||||
case T_CHAR: slow_case_addr = jni_GetCharField_addr(); break;
|
case T_CHAR: slow_case_addr = jni_GetCharField_addr(); break;
|
||||||
case T_SHORT: slow_case_addr = jni_GetShortField_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
|
// tail call
|
||||||
__ jump (ExternalAddress(slow_case_addr));
|
__ 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_INT: inc_counter_np(SharedRuntime::_jint_array_copy_ctr); return;
|
||||||
case T_LONG: inc_counter_np(SharedRuntime::_jlong_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;
|
case T_OBJECT: inc_counter_np(SharedRuntime::_oop_array_copy_ctr); return;
|
||||||
|
default: ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
ShouldNotReachHere();
|
|
||||||
#endif //PRODUCT
|
#endif //PRODUCT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1877,12 +1877,16 @@ void* os::get_default_process_handle() {
|
|||||||
return (void*)::dlopen(NULL, RTLD_LAZY);
|
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);
|
int fd = ::open(filename, O_RDONLY);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hdr != NULL) {
|
||||||
|
st->print_cr("%s", hdr);
|
||||||
|
}
|
||||||
|
|
||||||
char buf[33];
|
char buf[33];
|
||||||
int bytes;
|
int bytes;
|
||||||
buf[32] = '\0';
|
buf[32] = '\0';
|
||||||
@ -1975,6 +1979,8 @@ void os::print_os_info(outputStream* st) {
|
|||||||
|
|
||||||
os::Linux::print_proc_sys_info(st);
|
os::Linux::print_proc_sys_info(st);
|
||||||
|
|
||||||
|
os::Linux::print_ld_preload_file(st);
|
||||||
|
|
||||||
os::Linux::print_container_info(st);
|
os::Linux::print_container_info(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2133,6 +2139,11 @@ void os::Linux::print_full_memory_info(outputStream* st) {
|
|||||||
st->cr();
|
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) {
|
void os::Linux::print_container_info(outputStream* st) {
|
||||||
if (!OSContainer::is_containerized()) {
|
if (!OSContainer::is_containerized()) {
|
||||||
return;
|
return;
|
||||||
|
@ -114,6 +114,7 @@ class Linux {
|
|||||||
static void print_distro_info(outputStream* st);
|
static void print_distro_info(outputStream* st);
|
||||||
static void print_libversion_info(outputStream* st);
|
static void print_libversion_info(outputStream* st);
|
||||||
static void print_proc_sys_info(outputStream* st);
|
static void print_proc_sys_info(outputStream* st);
|
||||||
|
static void print_ld_preload_file(outputStream* st);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static bool _stack_is_executable;
|
static bool _stack_is_executable;
|
||||||
|
@ -47,11 +47,10 @@
|
|||||||
// the singleton class the_null_class_loader_data().
|
// the singleton class the_null_class_loader_data().
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/classLoaderData.hpp"
|
|
||||||
#include "classfile/classLoaderData.inline.hpp"
|
#include "classfile/classLoaderData.inline.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.inline.hpp"
|
||||||
#include "classfile/dictionary.hpp"
|
#include "classfile/dictionary.hpp"
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/metadataOnStackMark.hpp"
|
|
||||||
#include "classfile/moduleEntry.hpp"
|
#include "classfile/moduleEntry.hpp"
|
||||||
#include "classfile/packageEntry.hpp"
|
#include "classfile/packageEntry.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/symbolTable.hpp"
|
||||||
@ -60,9 +59,7 @@
|
|||||||
#include "logging/logStream.hpp"
|
#include "logging/logStream.hpp"
|
||||||
#include "memory/allocation.inline.hpp"
|
#include "memory/allocation.inline.hpp"
|
||||||
#include "memory/metadataFactory.hpp"
|
#include "memory/metadataFactory.hpp"
|
||||||
#include "memory/metaspaceShared.hpp"
|
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
#include "memory/universe.hpp"
|
|
||||||
#include "oops/access.inline.hpp"
|
#include "oops/access.inline.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "oops/oopHandle.inline.hpp"
|
#include "oops/oopHandle.inline.hpp"
|
||||||
@ -72,14 +69,10 @@
|
|||||||
#include "runtime/mutex.hpp"
|
#include "runtime/mutex.hpp"
|
||||||
#include "runtime/orderAccess.hpp"
|
#include "runtime/orderAccess.hpp"
|
||||||
#include "runtime/safepoint.hpp"
|
#include "runtime/safepoint.hpp"
|
||||||
#include "runtime/safepointVerifiers.hpp"
|
|
||||||
#include "utilities/growableArray.hpp"
|
#include "utilities/growableArray.hpp"
|
||||||
#include "utilities/macros.hpp"
|
#include "utilities/macros.hpp"
|
||||||
#include "utilities/ostream.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;
|
ClassLoaderData * ClassLoaderData::_the_null_class_loader_data = NULL;
|
||||||
|
|
||||||
void ClassLoaderData::init_null_class_loader_data() {
|
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()) {
|
for (Klass* k = OrderAccess::load_acquire(&_klasses); k != NULL; k = k->next_link()) {
|
||||||
// Do not filter ArrayKlass oops here...
|
// Do not filter ArrayKlass oops here...
|
||||||
if (k->is_array_klass() || (k->is_instance_klass() && InstanceKlass::cast(k)->is_loaded())) {
|
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);
|
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 */) {
|
void ClassLoaderData::add_class(Klass* k, bool publicize /* true */) {
|
||||||
{
|
{
|
||||||
MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag);
|
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) {
|
void ClassLoaderData::initialize_holder(Handle loader_or_mirror) {
|
||||||
if (loader_or_mirror() != NULL) {
|
if (loader_or_mirror() != NULL) {
|
||||||
assert(_holder.is_null(), "never replace holders");
|
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");
|
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
|
||||||
|
|
||||||
// Adjust global class iterator.
|
// Adjust global class iterator.
|
||||||
static_klass_iterator.adjust_saved_class(scratch_class);
|
ClassLoaderDataGraph::adjust_saved_class(scratch_class);
|
||||||
|
|
||||||
Klass* prev = NULL;
|
Klass* prev = NULL;
|
||||||
for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
|
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.
|
// if they are not already on the _klasses list.
|
||||||
free_deallocate_list_C_heap_structures();
|
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.
|
// after erroneous classes are released.
|
||||||
classes_do(InstanceKlass::notify_unload_class);
|
classes_do(InstanceKlass::unload_class);
|
||||||
|
|
||||||
// Clean up global class iterator for compiler
|
// Clean up global class iterator for compiler
|
||||||
static_klass_iterator.adjust_saved_class(this);
|
ClassLoaderDataGraph::adjust_saved_class(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleEntryTable* ClassLoaderData::modules() {
|
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
|
// 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
|
// 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
|
// 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;
|
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,
|
// ClassLoaderData are stored in the runtime representation of classes,
|
||||||
// and provides iterators for root tracing and other GC operations.
|
// and provides iterators for root tracing and other GC operations.
|
||||||
|
|
||||||
class ClassLoaderData;
|
class ClassLoaderDataGraph;
|
||||||
class JNIMethodBlock;
|
class JNIMethodBlock;
|
||||||
class Metadebug;
|
|
||||||
class ModuleEntry;
|
class ModuleEntry;
|
||||||
class PackageEntry;
|
class PackageEntry;
|
||||||
class ModuleEntryTable;
|
class ModuleEntryTable;
|
||||||
@ -63,136 +62,6 @@ class PackageEntryTable;
|
|||||||
class DictionaryEntry;
|
class DictionaryEntry;
|
||||||
class Dictionary;
|
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
|
// ClassLoaderData class
|
||||||
|
|
||||||
class ClassLoaderData : public CHeapObj<mtClass> {
|
class ClassLoaderData : public CHeapObj<mtClass> {
|
||||||
@ -448,31 +317,4 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
|||||||
JFR_ONLY(DEFINE_TRACE_ID_METHODS;)
|
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
|
#endif // SHARE_VM_CLASSFILE_CLASSLOADERDATA_HPP
|
||||||
|
@ -55,54 +55,4 @@ inline ClassLoaderData* ClassLoaderData::class_loader_data(oop loader) {
|
|||||||
return loader_data;
|
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
|
#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 "precompiled.hpp"
|
||||||
|
|
||||||
#include "classfile/classLoaderData.inline.hpp"
|
#include "classfile/classLoaderData.inline.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/classLoaderHierarchyDCmd.hpp"
|
#include "classfile/classLoaderHierarchyDCmd.hpp"
|
||||||
#include "memory/allocation.hpp"
|
#include "memory/allocation.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/classLoaderData.inline.hpp"
|
#include "classfile/classLoaderData.inline.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/classLoaderStats.hpp"
|
#include "classfile/classLoaderStats.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "utilities/globalDefinitions.hpp"
|
#include "utilities/globalDefinitions.hpp"
|
||||||
|
@ -23,8 +23,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/dictionary.hpp"
|
|
||||||
#include "classfile/classLoaderData.inline.hpp"
|
#include "classfile/classLoaderData.inline.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
|
#include "classfile/dictionary.hpp"
|
||||||
#include "classfile/loaderConstraints.hpp"
|
#include "classfile/loaderConstraints.hpp"
|
||||||
#include "logging/log.hpp"
|
#include "logging/log.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "classfile/classFileStream.hpp"
|
#include "classfile/classFileStream.hpp"
|
||||||
#include "classfile/classLoader.hpp"
|
#include "classfile/classLoader.hpp"
|
||||||
#include "classfile/classLoaderData.inline.hpp"
|
#include "classfile/classLoaderData.inline.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.inline.hpp"
|
||||||
#include "classfile/classLoaderExt.hpp"
|
#include "classfile/classLoaderExt.hpp"
|
||||||
#include "classfile/dictionary.hpp"
|
#include "classfile/dictionary.hpp"
|
||||||
#include "classfile/javaClasses.inline.hpp"
|
#include "classfile/javaClasses.inline.hpp"
|
||||||
|
@ -218,18 +218,6 @@ int DependencyContext::remove_all_dependents() {
|
|||||||
return marked;
|
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
|
#ifndef PRODUCT
|
||||||
void DependencyContext::print_dependent_nmethods(bool verbose) {
|
void DependencyContext::print_dependent_nmethods(bool verbose) {
|
||||||
int idx = 0;
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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();
|
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
|
#ifndef PRODUCT
|
||||||
void print_dependent_nmethods(bool verbose);
|
void print_dependent_nmethods(bool verbose);
|
||||||
bool is_dependent_nmethod(nmethod* nm);
|
bool is_dependent_nmethod(nmethod* nm);
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/classLoaderData.hpp"
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/symbolTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/metadataOnStackMark.hpp"
|
#include "classfile/metadataOnStackMark.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/metadataOnStackMark.hpp"
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "gc/g1/g1BarrierSet.hpp"
|
#include "gc/g1/g1BarrierSet.hpp"
|
||||||
#include "gc/g1/g1CollectedHeap.inline.hpp"
|
#include "gc/g1/g1CollectedHeap.inline.hpp"
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/classLoaderData.hpp"
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "gc/g1/g1Analytics.hpp"
|
#include "gc/g1/g1Analytics.hpp"
|
||||||
#include "gc/g1/g1CollectedHeap.inline.hpp"
|
#include "gc/g1/g1CollectedHeap.inline.hpp"
|
||||||
#include "gc/g1/g1ConcurrentMark.inline.hpp"
|
#include "gc/g1/g1ConcurrentMark.inline.hpp"
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "gc/g1/g1CollectedHeap.hpp"
|
#include "gc/g1/g1CollectedHeap.hpp"
|
||||||
#include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
|
#include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
|
||||||
#include "gc/g1/g1FullCollector.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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -23,6 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "gc/g1/g1CollectedHeap.hpp"
|
#include "gc/g1/g1CollectedHeap.hpp"
|
||||||
#include "gc/g1/g1FullCollector.hpp"
|
#include "gc/g1/g1FullCollector.hpp"
|
||||||
#include "gc/g1/g1FullGCMarker.hpp"
|
#include "gc/g1/g1FullGCMarker.hpp"
|
||||||
|
@ -23,8 +23,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
|
||||||
#include "aot/aotLoader.hpp"
|
#include "aot/aotLoader.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "aot/aotLoader.hpp"
|
#include "aot/aotLoader.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "gc/parallel/parallelScavengeHeap.hpp"
|
#include "gc/parallel/parallelScavengeHeap.hpp"
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "aot/aotLoader.hpp"
|
#include "aot/aotLoader.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/symbolTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "aot/aotLoader.hpp"
|
#include "aot/aotLoader.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/javaClasses.inline.hpp"
|
#include "classfile/javaClasses.inline.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/symbolTable.hpp"
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "aot/aotLoader.hpp"
|
#include "aot/aotLoader.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "gc/parallel/gcTaskManager.hpp"
|
#include "gc/parallel/gcTaskManager.hpp"
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/symbolTable.hpp"
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "gc/shared/cardTableRS.hpp"
|
#include "gc/shared/cardTableRS.hpp"
|
||||||
#include "gc/shared/genCollectedHeap.hpp"
|
#include "gc/shared/genCollectedHeap.hpp"
|
||||||
#include "gc/shared/genOopClosures.hpp"
|
#include "gc/shared/genOopClosures.hpp"
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "aot/aotLoader.hpp"
|
#include "aot/aotLoader.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/symbolTable.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
|
@ -34,9 +34,9 @@
|
|||||||
// These fascilities are used for allocating, and initializing newly allocated objects.
|
// These fascilities are used for allocating, and initializing newly allocated objects.
|
||||||
|
|
||||||
class MemAllocator: StackObj {
|
class MemAllocator: StackObj {
|
||||||
|
protected:
|
||||||
class Allocation;
|
class Allocation;
|
||||||
|
|
||||||
protected:
|
|
||||||
CollectedHeap* const _heap;
|
CollectedHeap* const _heap;
|
||||||
Thread* const _thread;
|
Thread* const _thread;
|
||||||
Klass* const _klass;
|
Klass* const _klass;
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#ifndef SHARE_VM_GC_SHARED_PARALLELCLEANING_HPP
|
#ifndef SHARE_VM_GC_SHARED_PARALLELCLEANING_HPP
|
||||||
#define 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/oopStorageParState.hpp"
|
||||||
#include "gc/shared/stringdedup/stringDedup.hpp"
|
#include "gc/shared/stringdedup/stringDedup.hpp"
|
||||||
#include "gc/shared/workgroup.hpp"
|
#include "gc/shared/workgroup.hpp"
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/classLoaderData.hpp"
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "aot/aotLoader.hpp"
|
#include "aot/aotLoader.hpp"
|
||||||
#include "classfile/classLoaderData.hpp"
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "gc/shared/strongRootsScope.hpp"
|
#include "gc/shared/strongRootsScope.hpp"
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "aot/aotLoader.hpp"
|
#include "aot/aotLoader.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "gc/shared/strongRootsScope.hpp"
|
#include "gc/shared/strongRootsScope.hpp"
|
||||||
#include "jfr/leakprofiler/utilities/unifiedOop.hpp"
|
#include "jfr/leakprofiler/utilities/unifiedOop.hpp"
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/classLoaderData.hpp"
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "jfr/leakprofiler/utilities/saveRestore.hpp"
|
#include "jfr/leakprofiler/utilities/saveRestore.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
|
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/classLoaderData.hpp"
|
#include "classfile/classLoaderData.inline.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/moduleEntry.hpp"
|
#include "classfile/moduleEntry.hpp"
|
||||||
#include "classfile/packageEntry.hpp"
|
#include "classfile/packageEntry.hpp"
|
||||||
#include "jfr/jfrEvents.hpp"
|
#include "jfr/jfrEvents.hpp"
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "jvm.h"
|
#include "jvm.h"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/classLoaderStats.hpp"
|
#include "classfile/classLoaderStats.hpp"
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/classLoaderData.inline.hpp"
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/javaClasses.inline.hpp"
|
#include "classfile/javaClasses.inline.hpp"
|
||||||
#include "classfile/moduleEntry.hpp"
|
#include "classfile/moduleEntry.hpp"
|
||||||
#include "classfile/packageEntry.hpp"
|
#include "classfile/packageEntry.hpp"
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/classLoaderData.inline.hpp"
|
#include "classfile/classLoaderData.inline.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/moduleEntry.hpp"
|
#include "classfile/moduleEntry.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "gc/shared/collectedHeap.hpp"
|
#include "gc/shared/collectedHeap.hpp"
|
||||||
|
@ -23,8 +23,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
|
||||||
#include "aot/aotLoader.hpp"
|
#include "aot/aotLoader.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "gc/shared/collectedHeap.hpp"
|
#include "gc/shared/collectedHeap.hpp"
|
||||||
#include "logging/log.hpp"
|
#include "logging/log.hpp"
|
||||||
#include "logging/logStream.hpp"
|
#include "logging/logStream.hpp"
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "jvm.h"
|
#include "jvm.h"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/classListParser.hpp"
|
#include "classfile/classListParser.hpp"
|
||||||
#include "classfile/classLoaderExt.hpp"
|
#include "classfile/classLoaderExt.hpp"
|
||||||
#include "classfile/dictionary.hpp"
|
#include "classfile/dictionary.hpp"
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "aot/aotLoader.hpp"
|
#include "aot/aotLoader.hpp"
|
||||||
#include "classfile/classLoader.hpp"
|
#include "classfile/classLoader.hpp"
|
||||||
#include "classfile/classLoaderData.hpp"
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
|
@ -686,15 +686,6 @@ bool InstanceKlass::verify_code(TRAPS) {
|
|||||||
return Verifier::verify(this, should_verify_class(), THREAD);
|
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) {
|
void InstanceKlass::link_class(TRAPS) {
|
||||||
assert(is_loaded(), "must be loaded");
|
assert(is_loaded(), "must be loaded");
|
||||||
if (!is_linked()) {
|
if (!is_linked()) {
|
||||||
@ -2300,10 +2291,12 @@ void InstanceKlass::remove_unshareable_info() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlink the class
|
// Reset to the 'allocated' state to prevent any premature accessing to
|
||||||
if (is_linked()) {
|
// a shared class at runtime while the class is still being loaded and
|
||||||
unlink_class();
|
// 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);
|
MutexLocker ml(Compile_lock);
|
||||||
init_implementor();
|
init_implementor();
|
||||||
@ -2350,6 +2343,10 @@ void InstanceKlass::remove_java_mirror() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
|
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);
|
set_package(loader_data, CHECK);
|
||||||
Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
|
Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
|
||||||
|
|
||||||
@ -2417,7 +2414,10 @@ static void clear_all_breakpoints(Method* m) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void InstanceKlass::notify_unload_class(InstanceKlass* ik) {
|
void InstanceKlass::unload_class(InstanceKlass* ik) {
|
||||||
|
// Release dependencies.
|
||||||
|
ik->dependencies().remove_all_dependents();
|
||||||
|
|
||||||
// notify the debugger
|
// notify the debugger
|
||||||
if (JvmtiExport::should_post_class_unload()) {
|
if (JvmtiExport::should_post_class_unload()) {
|
||||||
JvmtiExport::post_class_unload(ik);
|
JvmtiExport::post_class_unload(ik);
|
||||||
@ -2462,16 +2462,8 @@ void InstanceKlass::release_C_heap_structures() {
|
|||||||
FreeHeap(jmeths);
|
FreeHeap(jmeths);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release dependencies.
|
assert(_dep_context == DependencyContext::EMPTY,
|
||||||
// It is desirable to use DC::remove_all_dependents() here, but, unfortunately,
|
"dependencies should already be cleaned");
|
||||||
// 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();
|
|
||||||
|
|
||||||
#if INCLUDE_JVMTI
|
#if INCLUDE_JVMTI
|
||||||
// Deallocate breakpoint records
|
// Deallocate breakpoint records
|
||||||
|
@ -542,7 +542,6 @@ public:
|
|||||||
void initialize(TRAPS);
|
void initialize(TRAPS);
|
||||||
void link_class(TRAPS);
|
void link_class(TRAPS);
|
||||||
bool link_class_or_fail(TRAPS); // returns false on failure
|
bool link_class_or_fail(TRAPS); // returns false on failure
|
||||||
void unlink_class();
|
|
||||||
void rewrite_class(TRAPS);
|
void rewrite_class(TRAPS);
|
||||||
void link_methods(TRAPS);
|
void link_methods(TRAPS);
|
||||||
Method* class_initializer() const;
|
Method* class_initializer() const;
|
||||||
@ -1180,7 +1179,7 @@ public:
|
|||||||
bool on_stack() const { return _constants->on_stack(); }
|
bool on_stack() const { return _constants->on_stack(); }
|
||||||
|
|
||||||
// callbacks for actions during class unloading
|
// 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);
|
static void release_C_heap_structures(InstanceKlass* ik);
|
||||||
|
|
||||||
// Naming
|
// Naming
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "jvm.h"
|
#include "jvm.h"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/metadataOnStackMark.hpp"
|
#include "classfile/metadataOnStackMark.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "jvmtifiles/jvmtiEnv.hpp"
|
#include "jvmtifiles/jvmtiEnv.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
|
@ -23,8 +23,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/dictionary.hpp"
|
#include "classfile/dictionary.hpp"
|
||||||
#include "classfile/classLoaderData.inline.hpp"
|
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "gc/shared/collectedHeap.hpp"
|
#include "gc/shared/collectedHeap.hpp"
|
||||||
#include "memory/universe.hpp"
|
#include "memory/universe.hpp"
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "aot/aotLoader.hpp"
|
#include "aot/aotLoader.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/classFileStream.hpp"
|
#include "classfile/classFileStream.hpp"
|
||||||
#include "classfile/metadataOnStackMark.hpp"
|
#include "classfile/metadataOnStackMark.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/javaClasses.inline.hpp"
|
#include "classfile/javaClasses.inline.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/symbolTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
#include "classfile/classLoaderData.hpp"
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/modules.hpp"
|
#include "classfile/modules.hpp"
|
||||||
#include "classfile/protectionDomainCache.hpp"
|
#include "classfile/protectionDomainCache.hpp"
|
||||||
#include "classfile/stringTable.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() },
|
{ "CreateMinidumpOnCrash", JDK_Version::jdk(9), JDK_Version::undefined(), JDK_Version::undefined() },
|
||||||
{ "MustCallLoadClassInternal", JDK_Version::jdk(10), JDK_Version::jdk(11), JDK_Version::jdk(12) },
|
{ "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) },
|
{ "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 --------------
|
// -------------- Obsolete Flags - sorted by expired_in --------------
|
||||||
{ "CheckAssertionStatusDirectives",JDK_Version::undefined(), JDK_Version::jdk(11), JDK_Version::jdk(12) },
|
{ "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);
|
UNSUPPORTED_OPTION(UseLargePages);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(AIX)
|
||||||
|
UNSUPPORTED_OPTION(AllocateHeapAt);
|
||||||
|
#endif
|
||||||
|
|
||||||
ArgumentsExt::report_unsupported_options();
|
ArgumentsExt::report_unsupported_options();
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "jfr/jfrEvents.hpp"
|
#include "jfr/jfrEvents.hpp"
|
||||||
#include "jfr/support/jfrThreadId.hpp"
|
#include "jfr/support/jfrThreadId.hpp"
|
||||||
#include "logging/log.hpp"
|
#include "logging/log.hpp"
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/classLoaderData.inline.hpp"
|
#include "classfile/classLoaderDataGraph.inline.hpp"
|
||||||
#include "code/compiledIC.hpp"
|
#include "code/compiledIC.hpp"
|
||||||
#include "code/nmethod.hpp"
|
#include "code/nmethod.hpp"
|
||||||
#include "code/scopeDesc.hpp"
|
#include "code/scopeDesc.hpp"
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "jvm.h"
|
#include "jvm.h"
|
||||||
#include "aot/aotLoader.hpp"
|
#include "aot/aotLoader.hpp"
|
||||||
#include "classfile/classLoader.hpp"
|
#include "classfile/classLoader.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/classLoaderData.inline.hpp"
|
#include "classfile/classLoaderDataGraph.inline.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "gc/shared/collectedHeap.inline.hpp"
|
#include "gc/shared/collectedHeap.inline.hpp"
|
||||||
|
@ -110,7 +110,7 @@ static int Knob_Poverty = 1000;
|
|||||||
static int Knob_FixedSpin = 0;
|
static int Knob_FixedSpin = 0;
|
||||||
static int Knob_PreSpin = 10; // 20-100 likely better
|
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:
|
// Theory of operations -- Monitors lists, thread residency, etc:
|
||||||
@ -428,7 +428,7 @@ void ObjectMonitor::EnterI(TRAPS) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeferredInitialize();
|
assert(InitDone, "Unexpectedly not initialized");
|
||||||
|
|
||||||
// We try one round of spinning *before* enqueueing Self.
|
// 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!");
|
assert(Self->is_Java_thread(), "Must be Java thread!");
|
||||||
JavaThread *jt = (JavaThread *)THREAD;
|
JavaThread *jt = (JavaThread *)THREAD;
|
||||||
|
|
||||||
DeferredInitialize();
|
assert(InitDone, "Unexpectedly not initialized");
|
||||||
|
|
||||||
if (THREAD != _owner) {
|
if (THREAD != _owner) {
|
||||||
if (THREAD->is_lock_owned ((address)_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!");
|
assert(Self->is_Java_thread(), "Must be Java thread!");
|
||||||
JavaThread *jt = (JavaThread *)THREAD;
|
JavaThread *jt = (JavaThread *)THREAD;
|
||||||
|
|
||||||
DeferredInitialize();
|
assert(InitDone, "Unexpectedly not initialized");
|
||||||
|
|
||||||
// Throw IMSX or IEX.
|
// Throw IMSX or IEX.
|
||||||
CHECK_OWNER();
|
CHECK_OWNER();
|
||||||
@ -1888,9 +1888,14 @@ PerfLongVariable * ObjectMonitor::_sync_MonExtant = NULL;
|
|||||||
// be protected - like so many things - by the MonitorCache_lock.
|
// be protected - like so many things - by the MonitorCache_lock.
|
||||||
|
|
||||||
void ObjectMonitor::Initialize() {
|
void ObjectMonitor::Initialize() {
|
||||||
static int InitializationCompleted = 0;
|
assert(!InitDone, "invariant");
|
||||||
assert(InitializationCompleted == 0, "invariant");
|
|
||||||
InitializationCompleted = 1;
|
if (!os::is_MP()) {
|
||||||
|
Knob_SpinLimit = 0;
|
||||||
|
Knob_PreSpin = 0;
|
||||||
|
Knob_FixedSpin = -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (UsePerfData) {
|
if (UsePerfData) {
|
||||||
EXCEPTION_MARK;
|
EXCEPTION_MARK;
|
||||||
#define NEWPERFCOUNTER(n) \
|
#define NEWPERFCOUNTER(n) \
|
||||||
@ -1913,26 +1918,6 @@ void ObjectMonitor::Initialize() {
|
|||||||
#undef NEWPERFCOUNTER
|
#undef NEWPERFCOUNTER
|
||||||
#undef NEWPERFVARIABLE
|
#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:
|
private:
|
||||||
void AddWaiter(ObjectWaiter * waiter);
|
void AddWaiter(ObjectWaiter * waiter);
|
||||||
static void DeferredInitialize();
|
|
||||||
void INotify(Thread * Self);
|
void INotify(Thread * Self);
|
||||||
ObjectWaiter * DequeueWaiter();
|
ObjectWaiter * DequeueWaiter();
|
||||||
void DequeueSpecificWaiter(ObjectWaiter * waiter);
|
void DequeueSpecificWaiter(ObjectWaiter * waiter);
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/classLoaderData.inline.hpp"
|
#include "classfile/classLoaderDataGraph.inline.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/symbolTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "ci/ciObjArrayKlass.hpp"
|
#include "ci/ciObjArrayKlass.hpp"
|
||||||
#include "ci/ciSymbol.hpp"
|
#include "ci/ciSymbol.hpp"
|
||||||
#include "classfile/compactHashtable.hpp"
|
#include "classfile/compactHashtable.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/dictionary.hpp"
|
#include "classfile/dictionary.hpp"
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/stringTable.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)"
|
#define HOTSPOT_BUILD_COMPILER "MS VC++ 14.0 (VS2015)"
|
||||||
#elif _MSC_VER == 1912
|
#elif _MSC_VER == 1912
|
||||||
#define HOTSPOT_BUILD_COMPILER "MS VC++ 15.5 (VS2017)"
|
#define HOTSPOT_BUILD_COMPILER "MS VC++ 15.5 (VS2017)"
|
||||||
|
#elif _MSC_VER == 1913
|
||||||
|
#define HOTSPOT_BUILD_COMPILER "MS VC++ 15.6 (VS2017)"
|
||||||
#else
|
#else
|
||||||
#define HOTSPOT_BUILD_COMPILER "unknown MS VC++:" XSTR(_MSC_VER)
|
#define HOTSPOT_BUILD_COMPILER "unknown MS VC++:" XSTR(_MSC_VER)
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "jvm.h"
|
#include "jvm.h"
|
||||||
|
#include "classfile/classLoaderData.inline.hpp"
|
||||||
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/symbolTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
|
||||||
#include "classfile/classLoaderData.inline.hpp"
|
#include "classfile/classLoaderDataGraph.inline.hpp"
|
||||||
#include "memory/allocation.hpp"
|
#include "memory/allocation.hpp"
|
||||||
#include "runtime/safepoint.hpp"
|
#include "runtime/safepoint.hpp"
|
||||||
#include "runtime/thread.inline.hpp"
|
#include "runtime/thread.inline.hpp"
|
||||||
|
@ -28,6 +28,7 @@ package java.util;
|
|||||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||||
import jdk.internal.util.ArraysSupport;
|
import jdk.internal.util.ArraysSupport;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.util.concurrent.ForkJoinPool;
|
import java.util.concurrent.ForkJoinPool;
|
||||||
import java.util.function.BinaryOperator;
|
import java.util.function.BinaryOperator;
|
||||||
@ -4288,21 +4289,41 @@ public class Arrays {
|
|||||||
// Misc
|
// Misc
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a fixed-size list backed by the specified array. (Changes to
|
* Returns a fixed-size list backed by the specified array. Changes made to
|
||||||
* the returned list "write through" to the array.) This method acts
|
* the array will be visible in the returned list, and changes made to the
|
||||||
* as bridge between array-based and collection-based APIs, in
|
* list will be visible in the array. The returned list is
|
||||||
* combination with {@link Collection#toArray}. The returned list is
|
* {@link Serializable} and implements {@link RandomAccess}.
|
||||||
* 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
|
* <p>This method also provides a convenient way to create a fixed-size
|
||||||
* list initialized to contain several elements:
|
* list initialized to contain several elements:
|
||||||
* <pre>
|
* <pre>{@code
|
||||||
* List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
|
* List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
|
||||||
* </pre>
|
* }</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 <T> the class of the objects in the array
|
||||||
* @param a the array by which the list will be backed
|
* @param a the array by which the list will be backed
|
||||||
* @return a list view of the specified array
|
* @return a list view of the specified array
|
||||||
|
* @throws NullPointerException if the specified array is {@code null}
|
||||||
*/
|
*/
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
@SuppressWarnings("varargs")
|
@SuppressWarnings("varargs")
|
||||||
|
@ -957,17 +957,17 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
|||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
static final class UniExceptionally<T> extends UniCompletion<T,T> {
|
static final class UniExceptionally<T> extends UniCompletion<T,T> {
|
||||||
Function<? super Throwable, ? extends T> fn;
|
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) {
|
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
|
final CompletableFuture<T> tryFire(int mode) {
|
||||||
// assert mode != ASYNC;
|
|
||||||
CompletableFuture<T> d; CompletableFuture<T> a;
|
CompletableFuture<T> d; CompletableFuture<T> a;
|
||||||
Object r; Function<? super Throwable, ? extends T> f;
|
Object r; Function<? super Throwable, ? extends T> f;
|
||||||
if ((d = dep) == null || (f = fn) == null
|
if ((d = dep) == null || (f = fn) == null
|
||||||
|| (a = src) == null || (r = a.result) == null
|
|| (a = src) == null || (r = a.result) == null
|
||||||
|| !d.uniExceptionally(r, f, this))
|
|| !d.uniExceptionally(r, f, mode > 0 ? null : this))
|
||||||
return null;
|
return null;
|
||||||
dep = null; src = null; fn = null;
|
dep = null; src = null; fn = null;
|
||||||
return d.postFire(a, mode);
|
return d.postFire(a, mode);
|
||||||
@ -980,11 +980,11 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
|||||||
Throwable x;
|
Throwable x;
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
try {
|
try {
|
||||||
if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) {
|
if (c != null && !c.claim())
|
||||||
if (c != null && !c.claim())
|
return false;
|
||||||
return false;
|
if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
|
||||||
completeValue(f.apply(x));
|
completeValue(f.apply(x));
|
||||||
} else
|
else
|
||||||
internalComplete(r);
|
internalComplete(r);
|
||||||
} catch (Throwable ex) {
|
} catch (Throwable ex) {
|
||||||
completeThrowable(ex);
|
completeThrowable(ex);
|
||||||
@ -994,14 +994,88 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private CompletableFuture<T> uniExceptionallyStage(
|
private CompletableFuture<T> uniExceptionallyStage(
|
||||||
Function<Throwable, ? extends T> f) {
|
Executor e, Function<Throwable, ? extends T> f) {
|
||||||
if (f == null) throw new NullPointerException();
|
if (f == null) throw new NullPointerException();
|
||||||
CompletableFuture<T> d = newIncompleteFuture();
|
CompletableFuture<T> d = newIncompleteFuture();
|
||||||
Object r;
|
Object r;
|
||||||
if ((r = result) == null)
|
if ((r = result) == null)
|
||||||
unipush(new UniExceptionally<T>(d, this, f));
|
unipush(new UniExceptionally<T>(e, d, this, f));
|
||||||
else
|
else if (e == null)
|
||||||
d.uniExceptionally(r, f, 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;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1093,7 +1167,7 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
|||||||
Object r, s; Throwable x;
|
Object r, s; Throwable x;
|
||||||
if ((r = result) == null)
|
if ((r = result) == null)
|
||||||
unipush(new UniCompose<T,V>(e, d, this, f));
|
unipush(new UniCompose<T,V>(e, d, this, f));
|
||||||
else if (e == null) {
|
else {
|
||||||
if (r instanceof AltResult) {
|
if (r instanceof AltResult) {
|
||||||
if ((x = ((AltResult)r).ex) != null) {
|
if ((x = ((AltResult)r).ex) != null) {
|
||||||
d.result = encodeThrowable(x, r);
|
d.result = encodeThrowable(x, r);
|
||||||
@ -1102,23 +1176,20 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
|||||||
r = null;
|
r = null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@SuppressWarnings("unchecked") T t = (T) r;
|
if (e != null)
|
||||||
CompletableFuture<V> g = f.apply(t).toCompletableFuture();
|
e.execute(new UniCompose<T,V>(null, d, this, f));
|
||||||
if ((s = g.result) != null)
|
|
||||||
d.result = encodeRelay(s);
|
|
||||||
else {
|
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) {
|
} catch (Throwable ex) {
|
||||||
d.result = encodeThrowable(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;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1898,7 +1969,7 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
|||||||
* Creates a new complete CompletableFuture with given encoded result.
|
* Creates a new complete CompletableFuture with given encoded result.
|
||||||
*/
|
*/
|
||||||
CompletableFuture(Object r) {
|
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;
|
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(
|
public CompletableFuture<T> exceptionally(
|
||||||
Function<Throwable, ? extends T> fn) {
|
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 -------------- */
|
/* ------------- Arbitrary-arity constructions -------------- */
|
||||||
|
|
||||||
|
@ -850,6 +850,130 @@ public interface CompletionStage<T> {
|
|||||||
public CompletionStage<T> exceptionally
|
public CompletionStage<T> exceptionally
|
||||||
(Function<Throwable, ? extends T> fn);
|
(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
|
* Returns a {@link CompletableFuture} maintaining the same
|
||||||
* completion properties as this stage. If this stage is already a
|
* completion properties as this stage. If this stage is already a
|
||||||
|
@ -234,7 +234,6 @@ module java.base {
|
|||||||
jdk.jconsole,
|
jdk.jconsole,
|
||||||
java.net.http;
|
java.net.http;
|
||||||
exports sun.net.www to
|
exports sun.net.www to
|
||||||
java.desktop,
|
|
||||||
java.net.http,
|
java.net.http,
|
||||||
jdk.jartool;
|
jdk.jartool;
|
||||||
exports sun.net.www.protocol.http to
|
exports sun.net.www.protocol.http to
|
||||||
|
@ -140,10 +140,6 @@ grant codeBase "jrt:/jdk.crypto.cryptoki" {
|
|||||||
permission java.io.FilePermission "<<ALL FILES>>", "read";
|
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" {
|
grant codeBase "jrt:/jdk.dynalink" {
|
||||||
permission java.security.AllPermission;
|
permission java.security.AllPermission;
|
||||||
};
|
};
|
||||||
|
@ -263,6 +263,8 @@ static char* nextToken(__ctx_args *pctx) {
|
|||||||
}
|
}
|
||||||
JLI_List_addSubstring(pctx->parts, anchor, nextc - anchor);
|
JLI_List_addSubstring(pctx->parts, anchor, nextc - anchor);
|
||||||
pctx->state = IN_ESCAPE;
|
pctx->state = IN_ESCAPE;
|
||||||
|
// anchor after backslash character
|
||||||
|
anchor = nextc + 1;
|
||||||
break;
|
break;
|
||||||
case '\'':
|
case '\'':
|
||||||
case '"':
|
case '"':
|
||||||
|
@ -170,6 +170,10 @@ getJavaIDFromLangID(LANGID langID)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (index = 0; index < 5; index++) {
|
||||||
|
elems[index] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (SetupI18nProps(MAKELCID(langID, SORT_DEFAULT),
|
if (SetupI18nProps(MAKELCID(langID, SORT_DEFAULT),
|
||||||
&(elems[0]), &(elems[1]), &(elems[2]), &(elems[3]), &(elems[4]))) {
|
&(elems[0]), &(elems[1]), &(elems[2]), &(elems[3]), &(elems[4]))) {
|
||||||
|
|
||||||
@ -183,15 +187,17 @@ getJavaIDFromLangID(LANGID langID)
|
|||||||
strcat(ret, elems[index]);
|
strcat(ret, elems[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (index = 0; index < 5; index++) {
|
|
||||||
free(elems[index]);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
free(ret);
|
free(ret);
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (index = 0; index < 5; index++) {
|
||||||
|
if (elems[index] != NULL) {
|
||||||
|
free(elems[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
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 nativeSetMenuState(final int menu, final boolean visible, final boolean enabled);
|
||||||
private static native void nativeSetDefaultMenuBar(final long menuBarPeer);
|
private static native void nativeSetDefaultMenuBar(final long menuBarPeer);
|
||||||
|
private static native void nativeActivateDefaultMenuBar(final long menuBarPeer);
|
||||||
|
|
||||||
static final _AppMenuBarHandler instance = new _AppMenuBarHandler();
|
static final _AppMenuBarHandler instance = new _AppMenuBarHandler();
|
||||||
static _AppMenuBarHandler getInstance() {
|
static _AppMenuBarHandler getInstance() {
|
||||||
@ -78,26 +79,18 @@ class _AppMenuBarHandler {
|
|||||||
|
|
||||||
void setDefaultMenuBar(final JMenuBar menuBar) {
|
void setDefaultMenuBar(final JMenuBar menuBar) {
|
||||||
installDefaultMenuBar(menuBar);
|
installDefaultMenuBar(menuBar);
|
||||||
if (menuBar == null) {
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
static boolean isMenuBarActivationNeeded() {
|
||||||
// scan the current frames, and see if any are foreground
|
// scan the current frames, and see if any are foreground
|
||||||
final Frame[] frames = Frame.getFrames();
|
final Frame[] frames = Frame.getFrames();
|
||||||
for (final Frame frame : frames) {
|
for (final Frame frame : frames) {
|
||||||
if (frame.isVisible() && !isFrameMinimized(frame)) {
|
if (frame.isVisible() && !isFrameMinimized(frame)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we have no foreground frames, then we have to "kick" the menubar
|
return true;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isFrameMinimized(final Frame frame) {
|
static boolean isFrameMinimized(final Frame frame) {
|
||||||
@ -150,6 +143,11 @@ class _AppMenuBarHandler {
|
|||||||
|
|
||||||
// grab the pointer to the CMenuBar, and retain it in native
|
// grab the pointer to the CMenuBar, and retain it in native
|
||||||
((CMenuBar) peer).execute(_AppMenuBarHandler::nativeSetDefaultMenuBar);
|
((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) {
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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 SparseBitShiftingTwoLayerArray secondLayerCache;
|
||||||
private HashMap<Integer, Float> generalCache;
|
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) {
|
public synchronized float get(final int index) {
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
if (-index < SECOND_LAYER_SIZE) {
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.
|
@SuppressWarnings("serial")// Safe: outer class is non-serializable.
|
||||||
private final class JButtonDelegate extends JButton {
|
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
|
@Override
|
||||||
public boolean hasFocus() {
|
public boolean hasFocus() {
|
||||||
return getTarget().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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.
|
@SuppressWarnings("serial")// Safe: outer class is non-serializable.
|
||||||
private final class JComboBoxDelegate extends JComboBox<String> {
|
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
|
@Override
|
||||||
public boolean hasFocus() {
|
public boolean hasFocus() {
|
||||||
return getTarget().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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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);
|
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
|
@Override
|
||||||
public boolean isLightweight() {
|
public boolean isLightweight() {
|
||||||
return false;
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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 {
|
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
|
@Override
|
||||||
public void replaceSelection(String content) {
|
public void replaceSelection(String content) {
|
||||||
getDocument().removeDocumentListener(LWTextAreaPeer.this);
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.
|
@SuppressWarnings("serial")// Safe: outer class is non-serializable.
|
||||||
private final class JPasswordFieldDelegate extends JPasswordField {
|
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
|
@Override
|
||||||
public void replaceSelection(String content) {
|
public void replaceSelection(String content) {
|
||||||
getDocument().removeDocumentListener(LWTextFieldPeer.this);
|
getDocument().removeDocumentListener(LWTextFieldPeer.this);
|
||||||
|
@ -165,8 +165,6 @@ public class CEmbeddedFrame extends EmbeddedFrame {
|
|||||||
: this;
|
: this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ignore focus "lost" native request as it may mistakenly
|
|
||||||
// deactivate active window (see 8001161)
|
|
||||||
if (globalFocusedWindow == this) {
|
if (globalFocusedWindow == this) {
|
||||||
responder.handleWindowFocusEvent(parentWindowActive, null);
|
responder.handleWindowFocusEvent(parentWindowActive, null);
|
||||||
}
|
}
|
||||||
@ -181,4 +179,19 @@ public class CEmbeddedFrame extends EmbeddedFrame {
|
|||||||
// another window.
|
// another window.
|
||||||
return globalFocusedWindow != null ? !globalFocusedWindow.isParentWindowActive() : true;
|
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
|
@Override
|
||||||
public boolean requestWindowFocus() {
|
public boolean requestWindowFocus() {
|
||||||
|
CEmbeddedFrame.updateGlobalFocusedWindow(target);
|
||||||
|
target.synthesizeWindowActivation(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1205,17 +1205,27 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void orderAboveSiblings() {
|
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();
|
CPlatformWindow rootOwner = getRootOwner();
|
||||||
if (rootOwner.isVisible() && !rootOwner.isIconified()) {
|
|
||||||
rootOwner.execute(CWrapper.NSWindow::orderFront);
|
|
||||||
}
|
|
||||||
// Do not order child windows of iconified owner.
|
// Do not order child windows of iconified owner.
|
||||||
if (!rootOwner.isIconified()) {
|
if (!rootOwner.isIconified()) {
|
||||||
final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor();
|
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
|
// NATIVE CALLBACKS
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
@ -537,10 +537,14 @@ static BOOL shouldUsePressAndHold() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
-(BOOL) isCodePointInUnicodeBlockNeedingIMEvent: (unichar) codePoint {
|
-(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))) {
|
((codePoint >= 0xFF00) && (codePoint <= 0xFFEF))) {
|
||||||
// Code point is in 'CJK Symbols and Punctuation' or
|
// 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 YES;
|
||||||
}
|
}
|
||||||
return NO;
|
return NO;
|
||||||
|
@ -477,6 +477,21 @@ AWT_ASSERT_APPKIT_THREAD;
|
|||||||
return isBlocked;
|
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
|
// Tests whether the corresponding Java platform window is visible or not
|
||||||
+ (BOOL) isJavaPlatformWindowVisible:(NSWindow *)window {
|
+ (BOOL) isJavaPlatformWindowVisible:(NSWindow *)window {
|
||||||
BOOL isVisible = NO;
|
BOOL isVisible = NO;
|
||||||
@ -543,7 +558,7 @@ AWT_ASSERT_APPKIT_THREAD;
|
|||||||
// NSWindow overrides
|
// NSWindow overrides
|
||||||
- (BOOL) canBecomeKeyWindow {
|
- (BOOL) canBecomeKeyWindow {
|
||||||
AWT_ASSERT_APPKIT_THREAD;
|
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 {
|
- (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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -35,10 +35,10 @@
|
|||||||
#import <JavaNativeFoundation/JavaNativeFoundation.h>
|
#import <JavaNativeFoundation/JavaNativeFoundation.h>
|
||||||
|
|
||||||
#import "CPopupMenu.h"
|
#import "CPopupMenu.h"
|
||||||
|
#import "CMenuBar.h"
|
||||||
#import "ThreadUtilities.h"
|
#import "ThreadUtilities.h"
|
||||||
#import "NSApplicationAWT.h"
|
#import "NSApplicationAWT.h"
|
||||||
|
|
||||||
|
|
||||||
#pragma mark App Menu helpers
|
#pragma mark App Menu helpers
|
||||||
|
|
||||||
// The following is a AWT convention?
|
// The following is a AWT convention?
|
||||||
@ -201,11 +201,11 @@ AWT_ASSERT_APPKIT_THREAD;
|
|||||||
|
|
||||||
self.fPreferencesMenu = (NSMenuItem*)[appMenu itemWithTag:PREFERENCES_TAG];
|
self.fPreferencesMenu = (NSMenuItem*)[appMenu itemWithTag:PREFERENCES_TAG];
|
||||||
self.fAboutMenu = (NSMenuItem*)[appMenu itemAtIndex:0];
|
self.fAboutMenu = (NSMenuItem*)[appMenu itemAtIndex:0];
|
||||||
|
|
||||||
NSDockTile *dockTile = [NSApp dockTile];
|
NSDockTile *dockTile = [NSApp dockTile];
|
||||||
self.fProgressIndicator = [[NSProgressIndicator alloc]
|
self.fProgressIndicator = [[NSProgressIndicator alloc]
|
||||||
initWithFrame:NSMakeRect(3.f, 0.f, dockTile.size.width - 6.f, 20.f)];
|
initWithFrame:NSMakeRect(3.f, 0.f, dockTile.size.width - 6.f, 20.f)];
|
||||||
|
|
||||||
[fProgressIndicator setStyle:NSProgressIndicatorBarStyle];
|
[fProgressIndicator setStyle:NSProgressIndicatorBarStyle];
|
||||||
[fProgressIndicator setIndeterminate:NO];
|
[fProgressIndicator setIndeterminate:NO];
|
||||||
[[dockTile contentView] addSubview:fProgressIndicator];
|
[[dockTile contentView] addSubview:fProgressIndicator];
|
||||||
@ -824,3 +824,23 @@ JNF_COCOA_ENTER(env);
|
|||||||
|
|
||||||
JNF_COCOA_EXIT(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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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);
|
getEventDispatcher().addLineMonitor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
doIO = true;
|
synchronized(lock) {
|
||||||
|
doIO = true;
|
||||||
// need to set Active and Started
|
// need to set Active and Started
|
||||||
// note: the current API always requires that
|
// note: the current API always requires that
|
||||||
// Started and Active are set at the same time...
|
// Started and Active are set at the same time...
|
||||||
if (isSource && stoppedWritten) {
|
if (isSource && stoppedWritten) {
|
||||||
setStarted(true);
|
setStarted(true);
|
||||||
setActive(true);
|
setActive(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Printer.trace) Printer.trace("<< DirectDL: implStart() succeeded");
|
if (Printer.trace) Printer.trace("<< DirectDL: implStart() succeeded");
|
||||||
@ -582,10 +583,10 @@ final class DirectAudioDevice extends AbstractMixer {
|
|||||||
// read/write thread, that's why isStartedRunning()
|
// read/write thread, that's why isStartedRunning()
|
||||||
// cannot be used
|
// cannot be used
|
||||||
doIO = false;
|
doIO = false;
|
||||||
|
setActive(false);
|
||||||
|
setStarted(false);
|
||||||
lock.notifyAll();
|
lock.notifyAll();
|
||||||
}
|
}
|
||||||
setActive(false);
|
|
||||||
setStarted(false);
|
|
||||||
stoppedWritten = false;
|
stoppedWritten = false;
|
||||||
|
|
||||||
if (Printer.trace) Printer.trace(" << DirectDL: implStop() succeeded");
|
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) {
|
if ((long)off + (long)len > (long)b.length) {
|
||||||
throw new ArrayIndexOutOfBoundsException(b.length);
|
throw new ArrayIndexOutOfBoundsException(b.length);
|
||||||
}
|
}
|
||||||
|
synchronized(lock) {
|
||||||
if (!isActive() && doIO) {
|
if (!isActive() && doIO) {
|
||||||
// this is not exactly correct... would be nicer
|
// this is not exactly correct... would be nicer
|
||||||
// if the native sub system sent a callback when IO really starts
|
// if the native sub system sent a callback when IO really
|
||||||
setActive(true);
|
// starts
|
||||||
setStarted(true);
|
setActive(true);
|
||||||
|
setStarted(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
int written = 0;
|
int written = 0;
|
||||||
while (!flushing) {
|
while (!flushing) {
|
||||||
@ -957,11 +960,14 @@ final class DirectAudioDevice extends AbstractMixer {
|
|||||||
if ((long)off + (long)len > (long)b.length) {
|
if ((long)off + (long)len > (long)b.length) {
|
||||||
throw new ArrayIndexOutOfBoundsException(b.length);
|
throw new ArrayIndexOutOfBoundsException(b.length);
|
||||||
}
|
}
|
||||||
if (!isActive() && doIO) {
|
synchronized(lock) {
|
||||||
// this is not exactly correct... would be nicer
|
if (!isActive() && doIO) {
|
||||||
// if the native sub system sent a callback when IO really starts
|
// this is not exactly correct... would be nicer
|
||||||
setActive(true);
|
// if the native sub system sent a callback when IO really
|
||||||
setStarted(true);
|
// starts
|
||||||
|
setActive(true);
|
||||||
|
setStarted(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
int read = 0;
|
int read = 0;
|
||||||
while (doIO && !flushing) {
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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");
|
String nm = System.getProperty("java.awt.headless");
|
||||||
|
|
||||||
if (nm == null) {
|
if (nm == null) {
|
||||||
/* No need to ask for DISPLAY when run in a browser */
|
final String osName = System.getProperty("os.name");
|
||||||
if (System.getProperty("javaplugin.version") != null) {
|
final String display = System.getenv("DISPLAY");
|
||||||
headless = defaultHeadless = Boolean.FALSE;
|
headless = defaultHeadless =
|
||||||
} 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 =
|
|
||||||
("Linux".equals(osName) ||
|
("Linux".equals(osName) ||
|
||||||
"SunOS".equals(osName) ||
|
"SunOS".equals(osName) ||
|
||||||
"FreeBSD".equals(osName) ||
|
"FreeBSD".equals(osName) ||
|
||||||
@ -188,8 +179,6 @@ public abstract class GraphicsEnvironment {
|
|||||||
"OpenBSD".equals(osName) ||
|
"OpenBSD".equals(osName) ||
|
||||||
"AIX".equals(osName)) &&
|
"AIX".equals(osName)) &&
|
||||||
(display == null || display.trim().isEmpty());
|
(display == null || display.trim().isEmpty());
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
headless = Boolean.valueOf(nm);
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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 securityWarningWidth = 0;
|
||||||
private transient volatile int securityWarningHeight = 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 {
|
static {
|
||||||
/* ensure that the necessary native libraries are loaded */
|
/* ensure that the necessary native libraries are loaded */
|
||||||
Toolkit.loadLibraries();
|
Toolkit.loadLibraries();
|
||||||
@ -3127,10 +3117,6 @@ public class Window extends Container implements Accessible {
|
|||||||
|
|
||||||
this.securityWarningWidth = 0;
|
this.securityWarningWidth = 0;
|
||||||
this.securityWarningHeight = 0;
|
this.securityWarningHeight = 0;
|
||||||
this.securityWarningPointX = 2.0;
|
|
||||||
this.securityWarningPointY = 0.0;
|
|
||||||
this.securityWarningAlignmentX = RIGHT_ALIGNMENT;
|
|
||||||
this.securityWarningAlignmentY = TOP_ALIGNMENT;
|
|
||||||
|
|
||||||
deserializeResources(s);
|
deserializeResources(s);
|
||||||
}
|
}
|
||||||
@ -4031,9 +4017,9 @@ public class Window extends Container implements Accessible {
|
|||||||
private Point2D calculateSecurityWarningPosition(double x, double y,
|
private Point2D calculateSecurityWarningPosition(double x, double y,
|
||||||
double w, double h)
|
double w, double h)
|
||||||
{
|
{
|
||||||
// The position according to the spec of SecurityWarning.setPosition()
|
// The desired location for the security warning
|
||||||
double wx = x + w * securityWarningAlignmentX + securityWarningPointX;
|
double wx = x + w * RIGHT_ALIGNMENT + 2.0;
|
||||||
double wy = y + h * securityWarningAlignmentY + securityWarningPointY;
|
double wy = y + h * TOP_ALIGNMENT + 0.0;
|
||||||
|
|
||||||
// First, make sure the warning is not too far from the window bounds
|
// First, make sure the warning is not too far from the window bounds
|
||||||
wx = Window.limit(wx,
|
wx = Window.limit(wx,
|
||||||
@ -4068,33 +4054,12 @@ public class Window extends Container implements Accessible {
|
|||||||
window.updateWindow();
|
window.updateWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dimension getSecurityWarningSize(Window window) {
|
|
||||||
return new Dimension(window.securityWarningWidth,
|
|
||||||
window.securityWarningHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSecurityWarningSize(Window window, int width, int height)
|
public void setSecurityWarningSize(Window window, int width, int height)
|
||||||
{
|
{
|
||||||
window.securityWarningWidth = width;
|
window.securityWarningWidth = width;
|
||||||
window.securityWarningHeight = height;
|
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,
|
public Point2D calculateSecurityWarningPosition(Window window,
|
||||||
double x, double y, double w, double h)
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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
|
private static final class DisplayChangedHandler implements
|
||||||
DisplayChangedListener {
|
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() {
|
public void displayChanged() {
|
||||||
scheduleDisplayChanges();
|
scheduleDisplayChanges();
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,8 @@ import javax.swing.JLabel;
|
|||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.basic.BasicHTML;
|
import javax.swing.plaf.basic.BasicHTML;
|
||||||
|
|
||||||
|
import jdk.internal.ref.CleanerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class which implements an arbitrary border
|
* A class which implements an arbitrary border
|
||||||
* with the addition of a String title in a
|
* with the addition of a String title in a
|
||||||
@ -759,22 +761,19 @@ public class TitledBorder extends AbstractBorder
|
|||||||
|
|
||||||
private void installPropertyChangeListeners() {
|
private void installPropertyChangeListeners() {
|
||||||
final WeakReference<TitledBorder> weakReference = new WeakReference<TitledBorder>(this);
|
final WeakReference<TitledBorder> weakReference = new WeakReference<TitledBorder>(this);
|
||||||
final PropertyChangeListener listener = new PropertyChangeListener() {
|
final PropertyChangeListener listener = evt -> {
|
||||||
@Override
|
TitledBorder tb = weakReference.get();
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
String prop = evt.getPropertyName();
|
||||||
if (weakReference.get() == null) {
|
if (tb != null && ("lookAndFeel".equals(prop) || "LabelUI".equals(prop))) {
|
||||||
UIManager.removePropertyChangeListener(this);
|
tb.label.updateUI();
|
||||||
UIManager.getDefaults().removePropertyChangeListener(this);
|
|
||||||
} else {
|
|
||||||
String prop = evt.getPropertyName();
|
|
||||||
if ("lookAndFeel".equals(prop) || "LabelUI".equals(prop)) {
|
|
||||||
label.updateUI();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
UIManager.addPropertyChangeListener(listener);
|
UIManager.addPropertyChangeListener(listener);
|
||||||
UIManager.getDefaults().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