Merge
This commit is contained in:
commit
53439611f0
1
.hgtags
1
.hgtags
@ -591,3 +591,4 @@ cddef3bde924f3ff4f17f3d369280cf69d0450e5 jdk-14+14
|
||||
d29f0181ba424a95d881aba5eabf2e393abcc70f jdk-14+16
|
||||
5c83830390baafb76a1fbe33443c57620bd45fb9 jdk-14+17
|
||||
e84d8379815ba0d3e50fb096d28c25894cb50b8c jdk-14+18
|
||||
9b67dd88a9313e982ec5f710a7747161bc8f0c23 jdk-14+19
|
||||
|
@ -489,31 +489,43 @@ AC_DEFUN([BASIC_SETUP_TOOL],
|
||||
# for unknown variables in the end.
|
||||
CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var"
|
||||
|
||||
tool_override=[$]$1
|
||||
AC_MSG_NOTICE([User supplied override $1="$tool_override"])
|
||||
|
||||
# Check if we try to supply an empty value
|
||||
if test "x[$]$1" = x; then
|
||||
AC_MSG_NOTICE([Setting user supplied tool $1= (no value)])
|
||||
if test "x$tool_override" = x; then
|
||||
AC_MSG_CHECKING([for $1])
|
||||
AC_MSG_RESULT([disabled])
|
||||
else
|
||||
# Split up override in command part and argument part
|
||||
tool_and_args=($tool_override)
|
||||
[ tool_command=${tool_and_args[0]} ]
|
||||
[ unset 'tool_and_args[0]' ]
|
||||
[ tool_args=${tool_and_args[@]} ]
|
||||
|
||||
# Check if the provided tool contains a complete path.
|
||||
tool_specified="[$]$1"
|
||||
tool_basename="${tool_specified##*/}"
|
||||
if test "x$tool_basename" = "x$tool_specified"; then
|
||||
tool_basename="${tool_command##*/}"
|
||||
if test "x$tool_basename" = "x$tool_command"; then
|
||||
# A command without a complete path is provided, search $PATH.
|
||||
AC_MSG_NOTICE([Will search for user supplied tool $1=$tool_basename])
|
||||
AC_MSG_NOTICE([Will search for user supplied tool "$tool_basename"])
|
||||
AC_PATH_PROG($1, $tool_basename)
|
||||
if test "x[$]$1" = x; then
|
||||
AC_MSG_ERROR([User supplied tool $tool_basename could not be found])
|
||||
AC_MSG_ERROR([User supplied tool $1="$tool_basename" could not be found])
|
||||
fi
|
||||
else
|
||||
# Otherwise we believe it is a complete path. Use it as it is.
|
||||
AC_MSG_NOTICE([Will use user supplied tool $1=$tool_specified])
|
||||
AC_MSG_CHECKING([for $1])
|
||||
if test ! -x "$tool_specified"; then
|
||||
AC_MSG_NOTICE([Will use user supplied tool "$tool_command"])
|
||||
AC_MSG_CHECKING([for $tool_command])
|
||||
if test ! -x "$tool_command"; then
|
||||
AC_MSG_RESULT([not found])
|
||||
AC_MSG_ERROR([User supplied tool $1=$tool_specified does not exist or is not executable])
|
||||
AC_MSG_ERROR([User supplied tool $1="$tool_command" does not exist or is not executable])
|
||||
fi
|
||||
AC_MSG_RESULT([$tool_specified])
|
||||
$1="$tool_command"
|
||||
AC_MSG_RESULT([found])
|
||||
fi
|
||||
if test "x$tool_args" != x; then
|
||||
# If we got arguments, re-append them to the command after the fixup.
|
||||
$1="[$]$1 $tool_args"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
@ -564,8 +564,8 @@ endif
|
||||
# Param 1 - The path to base the name of the log file / command line file on
|
||||
# Param 2 - The command to run
|
||||
ExecuteWithLog = \
|
||||
$(call LogCmdlines, Exececuting: [$(strip $2)]) \
|
||||
$(call MakeDir, $(dir $(strip $1))) \
|
||||
$(call LogCmdlines, Executing: [$(strip $2)]) \
|
||||
$(call MakeDir, $(dir $(strip $1)) $(MAKESUPPORT_OUTPUTDIR)/failure-logs) \
|
||||
$(call WriteFile, $2, $(strip $1).cmdline) \
|
||||
( $(RM) $(strip $1).log && $(strip $2) > >($(TEE) -a $(strip $1).log) 2> >($(TEE) -a $(strip $1).log >&2) || \
|
||||
( exitcode=$(DOLLAR)? && \
|
||||
|
@ -97,6 +97,7 @@ JVM_GetCPMethodSignatureUTF
|
||||
JVM_GetDeclaredClasses
|
||||
JVM_GetDeclaringClass
|
||||
JVM_GetEnclosingMethodInfo
|
||||
JVM_GetExtendedNPEMessage
|
||||
JVM_GetFieldIxModifiers
|
||||
JVM_GetFieldTypeAnnotations
|
||||
JVM_GetInheritedAccessControlContext
|
||||
|
@ -6352,7 +6352,7 @@ void MacroAssembler::string_indexof_char(Register str1, Register cnt1, Register
|
||||
movptr(result, str1);
|
||||
if (UseAVX >= 2) {
|
||||
cmpl(cnt1, stride);
|
||||
jcc(Assembler::less, SCAN_TO_CHAR_LOOP);
|
||||
jcc(Assembler::less, SCAN_TO_CHAR);
|
||||
cmpl(cnt1, 2*stride);
|
||||
jcc(Assembler::less, SCAN_TO_8_CHAR_INIT);
|
||||
movdl(vec1, ch);
|
||||
@ -6379,10 +6379,8 @@ void MacroAssembler::string_indexof_char(Register str1, Register cnt1, Register
|
||||
}
|
||||
bind(SCAN_TO_8_CHAR);
|
||||
cmpl(cnt1, stride);
|
||||
if (UseAVX >= 2) {
|
||||
jcc(Assembler::less, SCAN_TO_CHAR);
|
||||
} else {
|
||||
jcc(Assembler::less, SCAN_TO_CHAR_LOOP);
|
||||
jcc(Assembler::less, SCAN_TO_CHAR);
|
||||
if (UseAVX < 2) {
|
||||
movdl(vec1, ch);
|
||||
pshuflw(vec1, vec1, 0x00);
|
||||
pshufd(vec1, vec1, 0);
|
||||
|
@ -114,7 +114,8 @@ class MacroAssembler: public Assembler {
|
||||
// short offset operators (jmp and jcc)
|
||||
char* disp = (char*) &branch[1];
|
||||
int imm8 = target - (address) &disp[1];
|
||||
guarantee(this->is8bit(imm8), "Short forward jump exceeds 8-bit offset at %s:%d", file, line);
|
||||
guarantee(this->is8bit(imm8), "Short forward jump exceeds 8-bit offset at %s:%d",
|
||||
file == NULL ? "<NULL>" : file, line);
|
||||
*disp = imm8;
|
||||
} else {
|
||||
int* disp = (int*) &branch[(op == 0x0F || op == 0xC7)? 2: 1];
|
||||
|
@ -1304,6 +1304,97 @@ static void save_or_restore_arguments(MacroAssembler* masm,
|
||||
}
|
||||
}
|
||||
|
||||
// Registers need to be saved for runtime call
|
||||
static Register caller_saved_registers[] = {
|
||||
rcx, rdx, rsi, rdi
|
||||
};
|
||||
|
||||
// Save caller saved registers except r1 and r2
|
||||
static void save_registers_except(MacroAssembler* masm, Register r1, Register r2) {
|
||||
int reg_len = (int)(sizeof(caller_saved_registers) / sizeof(Register));
|
||||
for (int index = 0; index < reg_len; index ++) {
|
||||
Register this_reg = caller_saved_registers[index];
|
||||
if (this_reg != r1 && this_reg != r2) {
|
||||
__ push(this_reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Restore caller saved registers except r1 and r2
|
||||
static void restore_registers_except(MacroAssembler* masm, Register r1, Register r2) {
|
||||
int reg_len = (int)(sizeof(caller_saved_registers) / sizeof(Register));
|
||||
for (int index = reg_len - 1; index >= 0; index --) {
|
||||
Register this_reg = caller_saved_registers[index];
|
||||
if (this_reg != r1 && this_reg != r2) {
|
||||
__ pop(this_reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pin object, return pinned object or null in rax
|
||||
static void gen_pin_object(MacroAssembler* masm,
|
||||
Register thread, VMRegPair reg) {
|
||||
__ block_comment("gen_pin_object {");
|
||||
|
||||
Label is_null;
|
||||
Register tmp_reg = rax;
|
||||
VMRegPair tmp(tmp_reg->as_VMReg());
|
||||
if (reg.first()->is_stack()) {
|
||||
// Load the arg up from the stack
|
||||
simple_move32(masm, reg, tmp);
|
||||
reg = tmp;
|
||||
} else {
|
||||
__ movl(tmp_reg, reg.first()->as_Register());
|
||||
}
|
||||
__ testptr(reg.first()->as_Register(), reg.first()->as_Register());
|
||||
__ jccb(Assembler::equal, is_null);
|
||||
|
||||
// Save registers that may be used by runtime call
|
||||
Register arg = reg.first()->is_Register() ? reg.first()->as_Register() : noreg;
|
||||
save_registers_except(masm, arg, thread);
|
||||
|
||||
__ call_VM_leaf(
|
||||
CAST_FROM_FN_PTR(address, SharedRuntime::pin_object),
|
||||
thread, reg.first()->as_Register());
|
||||
|
||||
// Restore saved registers
|
||||
restore_registers_except(masm, arg, thread);
|
||||
|
||||
__ bind(is_null);
|
||||
__ block_comment("} gen_pin_object");
|
||||
}
|
||||
|
||||
// Unpin object
|
||||
static void gen_unpin_object(MacroAssembler* masm,
|
||||
Register thread, VMRegPair reg) {
|
||||
__ block_comment("gen_unpin_object {");
|
||||
Label is_null;
|
||||
|
||||
// temp register
|
||||
__ push(rax);
|
||||
Register tmp_reg = rax;
|
||||
VMRegPair tmp(tmp_reg->as_VMReg());
|
||||
|
||||
simple_move32(masm, reg, tmp);
|
||||
|
||||
__ testptr(rax, rax);
|
||||
__ jccb(Assembler::equal, is_null);
|
||||
|
||||
// Save registers that may be used by runtime call
|
||||
Register arg = reg.first()->is_Register() ? reg.first()->as_Register() : noreg;
|
||||
save_registers_except(masm, arg, thread);
|
||||
|
||||
__ call_VM_leaf(
|
||||
CAST_FROM_FN_PTR(address, SharedRuntime::unpin_object),
|
||||
thread, rax);
|
||||
|
||||
// Restore saved registers
|
||||
restore_registers_except(masm, arg, thread);
|
||||
__ bind(is_null);
|
||||
__ pop(rax);
|
||||
__ block_comment("} gen_unpin_object");
|
||||
}
|
||||
|
||||
// Check GCLocker::needs_gc and enter the runtime if it's true. This
|
||||
// keeps a new JNI critical region from starting until a GC has been
|
||||
// forced. Save down any oops in registers and describe them in an
|
||||
@ -1837,7 +1928,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
|
||||
__ get_thread(thread);
|
||||
|
||||
if (is_critical_native) {
|
||||
if (is_critical_native && !Universe::heap()->supports_object_pinning()) {
|
||||
check_needs_gc_for_critical_native(masm, thread, stack_slots, total_c_args, total_in_args,
|
||||
oop_handle_offset, oop_maps, in_regs, in_sig_bt);
|
||||
}
|
||||
@ -1875,6 +1966,11 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
//
|
||||
OopMap* map = new OopMap(stack_slots * 2, 0 /* arg_slots*/);
|
||||
|
||||
// Inbound arguments that need to be pinned for critical natives
|
||||
GrowableArray<int> pinned_args(total_in_args);
|
||||
// Current stack slot for storing register based array argument
|
||||
int pinned_slot = oop_handle_offset;
|
||||
|
||||
// Mark location of rbp,
|
||||
// map->set_callee_saved(VMRegImpl::stack2reg( stack_slots - 2), stack_slots * 2, 0, rbp->as_VMReg());
|
||||
|
||||
@ -1886,7 +1982,28 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
switch (in_sig_bt[i]) {
|
||||
case T_ARRAY:
|
||||
if (is_critical_native) {
|
||||
unpack_array_argument(masm, in_regs[i], in_elem_bt[i], out_regs[c_arg + 1], out_regs[c_arg]);
|
||||
VMRegPair in_arg = in_regs[i];
|
||||
if (Universe::heap()->supports_object_pinning()) {
|
||||
// gen_pin_object handles save and restore
|
||||
// of any clobbered registers
|
||||
gen_pin_object(masm, thread, in_arg);
|
||||
pinned_args.append(i);
|
||||
|
||||
// rax has pinned array
|
||||
VMRegPair result_reg(rax->as_VMReg());
|
||||
if (!in_arg.first()->is_stack()) {
|
||||
assert(pinned_slot <= stack_slots, "overflow");
|
||||
simple_move32(masm, result_reg, VMRegImpl::stack2reg(pinned_slot));
|
||||
pinned_slot += VMRegImpl::slots_per_word;
|
||||
} else {
|
||||
// Write back pinned value, it will be used to unpin this argument
|
||||
__ movptr(Address(rbp, reg2offset_in(in_arg.first())), result_reg.first()->as_Register());
|
||||
}
|
||||
// We have the array in register, use it
|
||||
in_arg = result_reg;
|
||||
}
|
||||
|
||||
unpack_array_argument(masm, in_arg, in_elem_bt[i], out_regs[c_arg + 1], out_regs[c_arg]);
|
||||
c_arg++;
|
||||
break;
|
||||
}
|
||||
@ -2079,6 +2196,26 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
default : ShouldNotReachHere();
|
||||
}
|
||||
|
||||
// unpin pinned arguments
|
||||
pinned_slot = oop_handle_offset;
|
||||
if (pinned_args.length() > 0) {
|
||||
// save return value that may be overwritten otherwise.
|
||||
save_native_result(masm, ret_type, stack_slots);
|
||||
for (int index = 0; index < pinned_args.length(); index ++) {
|
||||
int i = pinned_args.at(index);
|
||||
assert(pinned_slot <= stack_slots, "overflow");
|
||||
if (!in_regs[i].first()->is_stack()) {
|
||||
int offset = pinned_slot * VMRegImpl::stack_slot_size;
|
||||
__ movl(in_regs[i].first()->as_Register(), Address(rsp, offset));
|
||||
pinned_slot += VMRegImpl::slots_per_word;
|
||||
}
|
||||
// gen_pin_object handles save and restore
|
||||
// of any other clobbered registers
|
||||
gen_unpin_object(masm, thread, in_regs[i]);
|
||||
}
|
||||
restore_native_result(masm, ret_type, stack_slots);
|
||||
}
|
||||
|
||||
// Switch thread to "native transition" state before reading the synchronization state.
|
||||
// This additional state is necessary because reading and testing the synchronization
|
||||
// state is not atomic w.r.t. GC, as this scenario demonstrates:
|
||||
|
@ -1280,7 +1280,7 @@ const bool Matcher::match_rule_supported(int opcode) {
|
||||
case Op_AbsVS:
|
||||
case Op_AbsVI:
|
||||
case Op_AddReductionVI:
|
||||
if (UseSSE < 3) // requires at least SSE3
|
||||
if (UseSSE < 3 || !VM_Version::supports_ssse3()) // requires at least SSSE3
|
||||
ret_value = false;
|
||||
break;
|
||||
case Op_MulReductionVI:
|
||||
|
@ -1034,8 +1034,6 @@ jlong os::elapsed_frequency() {
|
||||
}
|
||||
|
||||
bool os::supports_vtime() { return true; }
|
||||
bool os::enable_vtime() { return false; }
|
||||
bool os::vtime_enabled() { return false; }
|
||||
|
||||
double os::elapsedVTime() {
|
||||
struct rusage usage;
|
||||
@ -3625,11 +3623,6 @@ void os::set_native_thread_name(const char *name) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool os::distribute_processes(uint length, uint* distribution) {
|
||||
// Not yet implemented.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool os::bind_to_processor(uint processor_id) {
|
||||
// Not yet implemented.
|
||||
return false;
|
||||
|
@ -44,7 +44,6 @@ class Aix {
|
||||
|
||||
static julong _physical_memory;
|
||||
static pthread_t _main_thread;
|
||||
static Mutex* _createThread_lock;
|
||||
static int _page_size;
|
||||
|
||||
// -1 = uninitialized, 0 = AIX, 1 = OS/400 (PASE)
|
||||
@ -90,8 +89,6 @@ class Aix {
|
||||
public:
|
||||
static void init_thread_fpu_state();
|
||||
static pthread_t main_thread(void) { return _main_thread; }
|
||||
static void set_createThread_lock(Mutex* lk) { _createThread_lock = lk; }
|
||||
static Mutex* createThread_lock(void) { return _createThread_lock; }
|
||||
static void hotspot_sigmask(Thread* thread);
|
||||
|
||||
// Given an address, returns the size of the page backing that address
|
||||
|
@ -64,8 +64,6 @@ inline void os::dll_unload(void *lib) {
|
||||
::dlclose(lib);
|
||||
}
|
||||
|
||||
inline const int os::default_file_open_flags() { return 0;}
|
||||
|
||||
inline jlong os::lseek(int fd, jlong offset, int whence) {
|
||||
return (jlong) ::lseek64(fd, offset, whence);
|
||||
}
|
||||
|
@ -877,8 +877,6 @@ jlong os::elapsed_frequency() {
|
||||
}
|
||||
|
||||
bool os::supports_vtime() { return true; }
|
||||
bool os::enable_vtime() { return false; }
|
||||
bool os::vtime_enabled() { return false; }
|
||||
|
||||
double os::elapsedVTime() {
|
||||
// better than nothing, but not much
|
||||
@ -3282,11 +3280,6 @@ void os::set_native_thread_name(const char *name) {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool os::distribute_processes(uint length, uint* distribution) {
|
||||
// Not yet implemented.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool os::bind_to_processor(uint processor_id) {
|
||||
// Not yet implemented.
|
||||
return false;
|
||||
|
@ -67,8 +67,6 @@ inline void os::dll_unload(void *lib) {
|
||||
::dlclose(lib);
|
||||
}
|
||||
|
||||
inline const int os::default_file_open_flags() { return 0;}
|
||||
|
||||
inline jlong os::lseek(int fd, jlong offset, int whence) {
|
||||
return (jlong) ::lseek(fd, offset, whence);
|
||||
}
|
||||
|
@ -131,14 +131,34 @@ class CgroupMemorySubsystem: CgroupSubsystem {
|
||||
* hierarchy. If set to true consider also memory.stat
|
||||
* file if everything else seems unlimited */
|
||||
bool _uses_mem_hierarchy;
|
||||
volatile jlong _memory_limit_in_bytes;
|
||||
volatile jlong _next_check_counter;
|
||||
|
||||
public:
|
||||
CgroupMemorySubsystem(char *root, char *mountpoint) : CgroupSubsystem::CgroupSubsystem(root, mountpoint) {
|
||||
_uses_mem_hierarchy = false;
|
||||
_memory_limit_in_bytes = -1;
|
||||
_next_check_counter = min_jlong;
|
||||
|
||||
}
|
||||
|
||||
bool is_hierarchical() { return _uses_mem_hierarchy; }
|
||||
void set_hierarchical(bool value) { _uses_mem_hierarchy = value; }
|
||||
|
||||
bool should_check_memory_limit() {
|
||||
return os::elapsed_counter() > _next_check_counter;
|
||||
}
|
||||
jlong memory_limit_in_bytes() { return _memory_limit_in_bytes; }
|
||||
void set_memory_limit_in_bytes(jlong value) {
|
||||
_memory_limit_in_bytes = value;
|
||||
// max memory limit is unlikely to change, but we want to remain
|
||||
// responsive to configuration changes. A very short (20ms) grace time
|
||||
// between re-read avoids excessive overhead during startup without
|
||||
// significantly reducing the VMs ability to promptly react to reduced
|
||||
// memory availability
|
||||
_next_check_counter = os::elapsed_counter() + (NANOSECS_PER_SEC/50);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CgroupMemorySubsystem* memory = NULL;
|
||||
@ -461,6 +481,16 @@ jlong OSContainer::uses_mem_hierarchy() {
|
||||
* OSCONTAINER_ERROR for not supported
|
||||
*/
|
||||
jlong OSContainer::memory_limit_in_bytes() {
|
||||
if (!memory->should_check_memory_limit()) {
|
||||
return memory->memory_limit_in_bytes();
|
||||
}
|
||||
jlong memory_limit = read_memory_limit_in_bytes();
|
||||
// Update CgroupMemorySubsystem to avoid re-reading container settings too often
|
||||
memory->set_memory_limit_in_bytes(memory_limit);
|
||||
return memory_limit;
|
||||
}
|
||||
|
||||
jlong OSContainer::read_memory_limit_in_bytes() {
|
||||
GET_CONTAINER_INFO(julong, memory, "/memory.limit_in_bytes",
|
||||
"Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, memlimit);
|
||||
|
||||
|
@ -36,6 +36,7 @@ class OSContainer: AllStatic {
|
||||
private:
|
||||
static bool _is_initialized;
|
||||
static bool _is_containerized;
|
||||
static jlong read_memory_limit_in_bytes();
|
||||
|
||||
public:
|
||||
static void init();
|
||||
|
@ -148,11 +148,9 @@ uintptr_t os::Linux::_initial_thread_stack_size = 0;
|
||||
|
||||
int (*os::Linux::_pthread_getcpuclockid)(pthread_t, clockid_t *) = NULL;
|
||||
int (*os::Linux::_pthread_setname_np)(pthread_t, const char*) = NULL;
|
||||
Mutex* os::Linux::_createThread_lock = NULL;
|
||||
pthread_t os::Linux::_main_thread;
|
||||
int os::Linux::_page_size = -1;
|
||||
bool os::Linux::_supports_fast_thread_cpu_time = false;
|
||||
uint32_t os::Linux::_os_version = 0;
|
||||
const char * os::Linux::_glibc_version = NULL;
|
||||
const char * os::Linux::_libpthread_version = NULL;
|
||||
|
||||
@ -1364,8 +1362,6 @@ jlong os::elapsed_frequency() {
|
||||
}
|
||||
|
||||
bool os::supports_vtime() { return true; }
|
||||
bool os::enable_vtime() { return false; }
|
||||
bool os::vtime_enabled() { return false; }
|
||||
|
||||
double os::elapsedVTime() {
|
||||
struct rusage usage;
|
||||
@ -4823,48 +4819,6 @@ jlong os::Linux::fast_thread_cpu_time(clockid_t clockid) {
|
||||
return (tp.tv_sec * NANOSECS_PER_SEC) + tp.tv_nsec;
|
||||
}
|
||||
|
||||
void os::Linux::initialize_os_info() {
|
||||
assert(_os_version == 0, "OS info already initialized");
|
||||
|
||||
struct utsname _uname;
|
||||
|
||||
uint32_t major;
|
||||
uint32_t minor;
|
||||
uint32_t fix;
|
||||
|
||||
int rc;
|
||||
|
||||
// Kernel version is unknown if
|
||||
// verification below fails.
|
||||
_os_version = 0x01000000;
|
||||
|
||||
rc = uname(&_uname);
|
||||
if (rc != -1) {
|
||||
|
||||
rc = sscanf(_uname.release,"%d.%d.%d", &major, &minor, &fix);
|
||||
if (rc == 3) {
|
||||
|
||||
if (major < 256 && minor < 256 && fix < 256) {
|
||||
// Kernel version format is as expected,
|
||||
// set it overriding unknown state.
|
||||
_os_version = (major << 16) |
|
||||
(minor << 8 ) |
|
||||
(fix << 0 ) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t os::Linux::os_version() {
|
||||
assert(_os_version != 0, "not initialized");
|
||||
return _os_version & 0x00FFFFFF;
|
||||
}
|
||||
|
||||
bool os::Linux::os_version_is_known() {
|
||||
assert(_os_version != 0, "not initialized");
|
||||
return _os_version & 0x01000000 ? false : true;
|
||||
}
|
||||
|
||||
/////
|
||||
// glibc on Linux platform uses non-documented flag
|
||||
// to indicate, that some special sort of signal
|
||||
@ -5084,8 +5038,6 @@ void os::init(void) {
|
||||
|
||||
Linux::initialize_system_info();
|
||||
|
||||
Linux::initialize_os_info();
|
||||
|
||||
os::Linux::CPUPerfTicks pticks;
|
||||
bool res = os::Linux::get_tick_information(&pticks, -1);
|
||||
|
||||
@ -5262,9 +5214,6 @@ jint os::init_2(void) {
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize lock used to serialize thread creation (see os::create_thread)
|
||||
Linux::set_createThread_lock(new Mutex(Mutex::leaf, "createThread_lock", false));
|
||||
|
||||
// at-exit methods are called in the reverse order of their registration.
|
||||
// atexit functions are called on return from main or as a result of a
|
||||
// call to exit(3C). There can be only 32 of these functions registered
|
||||
@ -5465,11 +5414,6 @@ void os::set_native_thread_name(const char *name) {
|
||||
}
|
||||
}
|
||||
|
||||
bool os::distribute_processes(uint length, uint* distribution) {
|
||||
// Not yet implemented.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool os::bind_to_processor(uint processor_id) {
|
||||
// Not yet implemented.
|
||||
return false;
|
||||
|
@ -55,20 +55,10 @@ class Linux {
|
||||
static GrowableArray<int>* _cpu_to_node;
|
||||
static GrowableArray<int>* _nindex_to_node;
|
||||
|
||||
// 0x00000000 = uninitialized,
|
||||
// 0x01000000 = kernel version unknown,
|
||||
// otherwise a 32-bit number:
|
||||
// Ox00AABBCC
|
||||
// AA, Major Version
|
||||
// BB, Minor Version
|
||||
// CC, Fix Version
|
||||
static uint32_t _os_version;
|
||||
|
||||
protected:
|
||||
|
||||
static julong _physical_memory;
|
||||
static pthread_t _main_thread;
|
||||
static Mutex* _createThread_lock;
|
||||
static int _page_size;
|
||||
|
||||
static julong available_memory();
|
||||
@ -136,8 +126,6 @@ class Linux {
|
||||
// returns kernel thread id (similar to LWP id on Solaris), which can be
|
||||
// used to access /proc
|
||||
static pid_t gettid();
|
||||
static void set_createThread_lock(Mutex* lk) { _createThread_lock = lk; }
|
||||
static Mutex* createThread_lock(void) { return _createThread_lock; }
|
||||
static void hotspot_sigmask(Thread* thread);
|
||||
|
||||
static address initial_thread_stack_bottom(void) { return _initial_thread_stack_bottom; }
|
||||
@ -196,7 +184,6 @@ class Linux {
|
||||
|
||||
// Stack overflow handling
|
||||
static bool manually_expand_stack(JavaThread * t, address addr);
|
||||
static int max_register_window_saves_before_flushing();
|
||||
|
||||
// fast POSIX clocks support
|
||||
static void fast_thread_clock_init(void);
|
||||
@ -211,10 +198,6 @@ class Linux {
|
||||
|
||||
static jlong fast_thread_cpu_time(clockid_t clockid);
|
||||
|
||||
static void initialize_os_info();
|
||||
static bool os_version_is_known();
|
||||
static uint32_t os_version();
|
||||
|
||||
// Stack repair handling
|
||||
|
||||
// none present
|
||||
|
@ -59,8 +59,6 @@ inline void os::dll_unload(void *lib) {
|
||||
::dlclose(lib);
|
||||
}
|
||||
|
||||
inline const int os::default_file_open_flags() { return 0;}
|
||||
|
||||
inline jlong os::lseek(int fd, jlong offset, int whence) {
|
||||
return (jlong) ::lseek64(fd, offset, whence);
|
||||
}
|
||||
|
@ -167,11 +167,6 @@ size_t os::lasterror(char *buf, size_t len) {
|
||||
return n;
|
||||
}
|
||||
|
||||
bool os::is_debugger_attached() {
|
||||
// not implemented
|
||||
return false;
|
||||
}
|
||||
|
||||
void os::wait_for_keypress_at_exit(void) {
|
||||
// don't do anything on posix platforms
|
||||
return;
|
||||
|
@ -265,8 +265,6 @@ void os::Solaris::try_enable_extended_io() {
|
||||
}
|
||||
}
|
||||
|
||||
static int _processors_online = 0;
|
||||
|
||||
jint os::Solaris::_os_thread_limit = 0;
|
||||
volatile jint os::Solaris::_os_thread_count = 0;
|
||||
|
||||
@ -291,7 +289,6 @@ static volatile hrtime_t max_hrtime = 0;
|
||||
|
||||
void os::Solaris::initialize_system_info() {
|
||||
set_processor_count(sysconf(_SC_NPROCESSORS_CONF));
|
||||
_processors_online = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
_physical_memory = (julong)sysconf(_SC_PHYS_PAGES) *
|
||||
(julong)sysconf(_SC_PAGESIZE);
|
||||
}
|
||||
@ -320,7 +317,6 @@ int os::active_processor_count() {
|
||||
// Query the number of cpus available to us.
|
||||
if (pset_info(pset, NULL, &pset_cpus, NULL) == 0) {
|
||||
assert(pset_cpus > 0 && pset_cpus <= online_cpus, "sanity check");
|
||||
_processors_online = pset_cpus;
|
||||
return pset_cpus;
|
||||
}
|
||||
}
|
||||
@ -328,136 +324,6 @@ int os::active_processor_count() {
|
||||
return online_cpus;
|
||||
}
|
||||
|
||||
static bool find_processors_in_pset(psetid_t pset,
|
||||
processorid_t** id_array,
|
||||
uint_t* id_length) {
|
||||
bool result = false;
|
||||
// Find the number of processors in the processor set.
|
||||
if (pset_info(pset, NULL, id_length, NULL) == 0) {
|
||||
// Make up an array to hold their ids.
|
||||
*id_array = NEW_C_HEAP_ARRAY(processorid_t, *id_length, mtInternal);
|
||||
// Fill in the array with their processor ids.
|
||||
if (pset_info(pset, NULL, id_length, *id_array) == 0) {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Callers of find_processors_online() must tolerate imprecise results --
|
||||
// the system configuration can change asynchronously because of DR
|
||||
// or explicit psradm operations.
|
||||
//
|
||||
// We also need to take care that the loop (below) terminates as the
|
||||
// number of processors online can change between the _SC_NPROCESSORS_ONLN
|
||||
// request and the loop that builds the list of processor ids. Unfortunately
|
||||
// there's no reliable way to determine the maximum valid processor id,
|
||||
// so we use a manifest constant, MAX_PROCESSOR_ID, instead. See p_online
|
||||
// man pages, which claim the processor id set is "sparse, but
|
||||
// not too sparse". MAX_PROCESSOR_ID is used to ensure that we eventually
|
||||
// exit the loop.
|
||||
//
|
||||
// In the future we'll be able to use sysconf(_SC_CPUID_MAX), but that's
|
||||
// not available on S8.0.
|
||||
|
||||
static bool find_processors_online(processorid_t** id_array,
|
||||
uint* id_length) {
|
||||
const processorid_t MAX_PROCESSOR_ID = 100000;
|
||||
// Find the number of processors online.
|
||||
*id_length = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
// Make up an array to hold their ids.
|
||||
*id_array = NEW_C_HEAP_ARRAY(processorid_t, *id_length, mtInternal);
|
||||
// Processors need not be numbered consecutively.
|
||||
long found = 0;
|
||||
processorid_t next = 0;
|
||||
while (found < *id_length && next < MAX_PROCESSOR_ID) {
|
||||
processor_info_t info;
|
||||
if (processor_info(next, &info) == 0) {
|
||||
// NB, PI_NOINTR processors are effectively online ...
|
||||
if (info.pi_state == P_ONLINE || info.pi_state == P_NOINTR) {
|
||||
(*id_array)[found] = next;
|
||||
found += 1;
|
||||
}
|
||||
}
|
||||
next += 1;
|
||||
}
|
||||
if (found < *id_length) {
|
||||
// The loop above didn't identify the expected number of processors.
|
||||
// We could always retry the operation, calling sysconf(_SC_NPROCESSORS_ONLN)
|
||||
// and re-running the loop, above, but there's no guarantee of progress
|
||||
// if the system configuration is in flux. Instead, we just return what
|
||||
// we've got. Note that in the worst case find_processors_online() could
|
||||
// return an empty set. (As a fall-back in the case of the empty set we
|
||||
// could just return the ID of the current processor).
|
||||
*id_length = found;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool assign_distribution(processorid_t* id_array,
|
||||
uint id_length,
|
||||
uint* distribution,
|
||||
uint distribution_length) {
|
||||
// We assume we can assign processorid_t's to uint's.
|
||||
assert(sizeof(processorid_t) == sizeof(uint),
|
||||
"can't convert processorid_t to uint");
|
||||
// Quick check to see if we won't succeed.
|
||||
if (id_length < distribution_length) {
|
||||
return false;
|
||||
}
|
||||
// Assign processor ids to the distribution.
|
||||
// Try to shuffle processors to distribute work across boards,
|
||||
// assuming 4 processors per board.
|
||||
const uint processors_per_board = ProcessDistributionStride;
|
||||
// Find the maximum processor id.
|
||||
processorid_t max_id = 0;
|
||||
for (uint m = 0; m < id_length; m += 1) {
|
||||
max_id = MAX2(max_id, id_array[m]);
|
||||
}
|
||||
// The next id, to limit loops.
|
||||
const processorid_t limit_id = max_id + 1;
|
||||
// Make up markers for available processors.
|
||||
bool* available_id = NEW_C_HEAP_ARRAY(bool, limit_id, mtInternal);
|
||||
for (uint c = 0; c < limit_id; c += 1) {
|
||||
available_id[c] = false;
|
||||
}
|
||||
for (uint a = 0; a < id_length; a += 1) {
|
||||
available_id[id_array[a]] = true;
|
||||
}
|
||||
// Step by "boards", then by "slot", copying to "assigned".
|
||||
// NEEDS_CLEANUP: The assignment of processors should be stateful,
|
||||
// remembering which processors have been assigned by
|
||||
// previous calls, etc., so as to distribute several
|
||||
// independent calls of this method. What we'd like is
|
||||
// It would be nice to have an API that let us ask
|
||||
// how many processes are bound to a processor,
|
||||
// but we don't have that, either.
|
||||
// In the short term, "board" is static so that
|
||||
// subsequent distributions don't all start at board 0.
|
||||
static uint board = 0;
|
||||
uint assigned = 0;
|
||||
// Until we've found enough processors ....
|
||||
while (assigned < distribution_length) {
|
||||
// ... find the next available processor in the board.
|
||||
for (uint slot = 0; slot < processors_per_board; slot += 1) {
|
||||
uint try_id = board * processors_per_board + slot;
|
||||
if ((try_id < limit_id) && (available_id[try_id] == true)) {
|
||||
distribution[assigned] = try_id;
|
||||
available_id[try_id] = false;
|
||||
assigned += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
board += 1;
|
||||
if (board * processors_per_board + 0 >= limit_id) {
|
||||
board = 0;
|
||||
}
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(bool, available_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
void os::set_native_thread_name(const char *name) {
|
||||
if (Solaris::_pthread_setname_np != NULL) {
|
||||
// Only the first 31 bytes of 'name' are processed by pthread_setname_np
|
||||
@ -470,31 +336,6 @@ void os::set_native_thread_name(const char *name) {
|
||||
}
|
||||
}
|
||||
|
||||
bool os::distribute_processes(uint length, uint* distribution) {
|
||||
bool result = false;
|
||||
// Find the processor id's of all the available CPUs.
|
||||
processorid_t* id_array = NULL;
|
||||
uint id_length = 0;
|
||||
// There are some races between querying information and using it,
|
||||
// since processor sets can change dynamically.
|
||||
psetid_t pset = PS_NONE;
|
||||
// Are we running in a processor set?
|
||||
if ((pset_bind(PS_QUERY, P_PID, P_MYID, &pset) == 0) && pset != PS_NONE) {
|
||||
result = find_processors_in_pset(pset, &id_array, &id_length);
|
||||
} else {
|
||||
result = find_processors_online(&id_array, &id_length);
|
||||
}
|
||||
if (result == true) {
|
||||
if (id_length >= length) {
|
||||
result = assign_distribution(id_array, id_length, distribution, length);
|
||||
} else {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(processorid_t, id_array);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool os::bind_to_processor(uint processor_id) {
|
||||
// We assume that a processorid_t can be stored in a uint.
|
||||
assert(sizeof(uint) == sizeof(processorid_t),
|
||||
@ -1237,8 +1078,6 @@ bool os::getTimesSecs(double* process_real_time,
|
||||
}
|
||||
|
||||
bool os::supports_vtime() { return true; }
|
||||
bool os::enable_vtime() { return false; }
|
||||
bool os::vtime_enabled() { return false; }
|
||||
|
||||
double os::elapsedVTime() {
|
||||
return (double)gethrvtime() / (double)hrtime_hz;
|
||||
|
@ -271,10 +271,6 @@ class Solaris {
|
||||
|
||||
static void correct_stack_boundaries_for_primordial_thread(Thread* thr);
|
||||
|
||||
// Stack overflow handling
|
||||
|
||||
static int max_register_window_saves_before_flushing();
|
||||
|
||||
// Stack repair handling
|
||||
|
||||
// none present
|
||||
|
@ -61,8 +61,6 @@ inline void os::map_stack_shadow_pages(address sp) {
|
||||
|
||||
inline void os::dll_unload(void *lib) { ::dlclose(lib); }
|
||||
|
||||
inline const int os::default_file_open_flags() { return 0;}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -826,11 +826,6 @@ void os::set_native_thread_name(const char *name) {
|
||||
} __except(EXCEPTION_EXECUTE_HANDLER) {}
|
||||
}
|
||||
|
||||
bool os::distribute_processes(uint length, uint* distribution) {
|
||||
// Not yet implemented.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool os::bind_to_processor(uint processor_id) {
|
||||
// Not yet implemented.
|
||||
return false;
|
||||
@ -911,8 +906,6 @@ FILETIME java_to_windows_time(jlong l) {
|
||||
}
|
||||
|
||||
bool os::supports_vtime() { return true; }
|
||||
bool os::enable_vtime() { return false; }
|
||||
bool os::vtime_enabled() { return false; }
|
||||
|
||||
double os::elapsedVTime() {
|
||||
FILETIME created;
|
||||
@ -3904,12 +3897,6 @@ void os::win32::setmode_streams() {
|
||||
_setmode(_fileno(stderr), _O_BINARY);
|
||||
}
|
||||
|
||||
|
||||
bool os::is_debugger_attached() {
|
||||
return IsDebuggerPresent() ? true : false;
|
||||
}
|
||||
|
||||
|
||||
void os::wait_for_keypress_at_exit(void) {
|
||||
if (PauseAtExit) {
|
||||
fprintf(stderr, "Press any key to continue...\n");
|
||||
|
@ -30,8 +30,6 @@
|
||||
|
||||
inline const char* os::dll_file_extension() { return ".dll"; }
|
||||
|
||||
inline const int os::default_file_open_flags() { return O_BINARY | O_NOINHERIT;}
|
||||
|
||||
inline void os::dll_unload(void *lib) {
|
||||
::FreeLibrary((HMODULE)lib);
|
||||
}
|
||||
|
@ -86,12 +86,6 @@ size_t os::Posix::_compiler_thread_min_stack_allowed = 104 * K;
|
||||
size_t os::Posix::_java_thread_min_stack_allowed = 86 * K;
|
||||
size_t os::Posix::_vm_internal_thread_min_stack_allowed = 128 * K;
|
||||
|
||||
int os::Solaris::max_register_window_saves_before_flushing() {
|
||||
// We should detect this at run time. For now, filling
|
||||
// in with a constant.
|
||||
return 8;
|
||||
}
|
||||
|
||||
static void handle_unflushed_register_windows(gwindows_t *win) {
|
||||
int restore_count = win->wbcnt;
|
||||
int i;
|
||||
|
@ -1545,7 +1545,7 @@ bool java_lang_Class::offsets_computed = false;
|
||||
int java_lang_Class::classRedefinedCount_offset = -1;
|
||||
|
||||
#define CLASS_FIELDS_DO(macro) \
|
||||
macro(classRedefinedCount_offset, k, "classRedefinedCount", int_signature, false) ; \
|
||||
macro(classRedefinedCount_offset, k, "classRedefinedCount", int_signature, false); \
|
||||
macro(_class_loader_offset, k, "classLoader", classloader_signature, false); \
|
||||
macro(_component_mirror_offset, k, "componentType", class_signature, false); \
|
||||
macro(_module_offset, k, "module", module_signature, false); \
|
||||
@ -1938,7 +1938,6 @@ static inline bool version_matches(Method* method, int version) {
|
||||
return method != NULL && (method->constants()->version() == version);
|
||||
}
|
||||
|
||||
|
||||
// This class provides a simple wrapper over the internal structure of
|
||||
// exception backtrace to insulate users of the backtrace from needing
|
||||
// to know what it looks like.
|
||||
@ -1950,7 +1949,11 @@ class BacktraceBuilder: public StackObj {
|
||||
typeArrayOop _methods;
|
||||
typeArrayOop _bcis;
|
||||
objArrayOop _mirrors;
|
||||
typeArrayOop _names; // needed to insulate method name against redefinition
|
||||
typeArrayOop _names; // Needed to insulate method name against redefinition.
|
||||
// This is set to a java.lang.Boolean(true) if the top frame
|
||||
// of the backtrace is omitted because it shall be hidden.
|
||||
// Else it is null.
|
||||
oop _has_hidden_top_frame;
|
||||
int _index;
|
||||
NoSafepointVerifier _nsv;
|
||||
|
||||
@ -1960,6 +1963,7 @@ class BacktraceBuilder: public StackObj {
|
||||
trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset,
|
||||
trace_names_offset = java_lang_Throwable::trace_names_offset,
|
||||
trace_next_offset = java_lang_Throwable::trace_next_offset,
|
||||
trace_hidden_offset = java_lang_Throwable::trace_hidden_offset,
|
||||
trace_size = java_lang_Throwable::trace_size,
|
||||
trace_chunk_size = java_lang_Throwable::trace_chunk_size
|
||||
};
|
||||
@ -1985,11 +1989,15 @@ class BacktraceBuilder: public StackObj {
|
||||
assert(names != NULL, "names array should be initialized in backtrace");
|
||||
return names;
|
||||
}
|
||||
static oop get_has_hidden_top_frame(objArrayHandle chunk) {
|
||||
oop hidden = chunk->obj_at(trace_hidden_offset);
|
||||
return hidden;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// constructor for new backtrace
|
||||
BacktraceBuilder(TRAPS): _head(NULL), _methods(NULL), _bcis(NULL), _mirrors(NULL), _names(NULL) {
|
||||
BacktraceBuilder(TRAPS): _head(NULL), _methods(NULL), _bcis(NULL), _mirrors(NULL), _names(NULL), _has_hidden_top_frame(NULL) {
|
||||
expand(CHECK);
|
||||
_backtrace = Handle(THREAD, _head);
|
||||
_index = 0;
|
||||
@ -2000,6 +2008,7 @@ class BacktraceBuilder: public StackObj {
|
||||
_bcis = get_bcis(backtrace);
|
||||
_mirrors = get_mirrors(backtrace);
|
||||
_names = get_names(backtrace);
|
||||
_has_hidden_top_frame = get_has_hidden_top_frame(backtrace);
|
||||
assert(_methods->length() == _bcis->length() &&
|
||||
_methods->length() == _mirrors->length() &&
|
||||
_mirrors->length() == _names->length(),
|
||||
@ -2037,6 +2046,7 @@ class BacktraceBuilder: public StackObj {
|
||||
new_head->obj_at_put(trace_bcis_offset, new_bcis());
|
||||
new_head->obj_at_put(trace_mirrors_offset, new_mirrors());
|
||||
new_head->obj_at_put(trace_names_offset, new_names());
|
||||
new_head->obj_at_put(trace_hidden_offset, NULL);
|
||||
|
||||
_head = new_head();
|
||||
_methods = new_methods();
|
||||
@ -2077,6 +2087,16 @@ class BacktraceBuilder: public StackObj {
|
||||
_index++;
|
||||
}
|
||||
|
||||
void set_has_hidden_top_frame(TRAPS) {
|
||||
if (_has_hidden_top_frame == NULL) {
|
||||
jvalue prim;
|
||||
prim.z = 1;
|
||||
PauseNoSafepointVerifier pnsv(&_nsv);
|
||||
_has_hidden_top_frame = java_lang_boxing_object::create(T_BOOLEAN, &prim, CHECK);
|
||||
_head->obj_at_put(trace_hidden_offset, _has_hidden_top_frame);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct BacktraceElement : public StackObj {
|
||||
@ -2406,7 +2426,13 @@ void java_lang_Throwable::fill_in_stack_trace(Handle throwable, const methodHand
|
||||
}
|
||||
}
|
||||
if (method->is_hidden()) {
|
||||
if (skip_hidden) continue;
|
||||
if (skip_hidden) {
|
||||
if (total_count == 0) {
|
||||
// The top frame will be hidden from the stack trace.
|
||||
bt.set_has_hidden_top_frame(CHECK);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
bt.push(method, bci, CHECK);
|
||||
total_count++;
|
||||
@ -2523,6 +2549,37 @@ void java_lang_Throwable::get_stack_trace_elements(Handle throwable,
|
||||
}
|
||||
}
|
||||
|
||||
bool java_lang_Throwable::get_top_method_and_bci(oop throwable, Method** method, int* bci) {
|
||||
Thread* THREAD = Thread::current();
|
||||
objArrayHandle result(THREAD, objArrayOop(backtrace(throwable)));
|
||||
BacktraceIterator iter(result, THREAD);
|
||||
// No backtrace available.
|
||||
if (!iter.repeat()) return false;
|
||||
|
||||
// If the exception happened in a frame that has been hidden, i.e.,
|
||||
// omitted from the back trace, we can not compute the message.
|
||||
oop hidden = ((objArrayOop)backtrace(throwable))->obj_at(trace_hidden_offset);
|
||||
if (hidden != NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get first backtrace element.
|
||||
BacktraceElement bte = iter.next(THREAD);
|
||||
|
||||
InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(bte._mirror()));
|
||||
assert(holder != NULL, "first element should be non-null");
|
||||
Method* m = holder->method_with_orig_idnum(bte._method_id, bte._version);
|
||||
|
||||
// Original version is no longer available.
|
||||
if (m == NULL || !version_matches(m, bte._version)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*method = m;
|
||||
*bci = bte._bci;
|
||||
return true;
|
||||
}
|
||||
|
||||
oop java_lang_StackTraceElement::create(const methodHandle& method, int bci, TRAPS) {
|
||||
// Allocate java.lang.StackTraceElement instance
|
||||
InstanceKlass* k = SystemDictionary::StackTraceElement_klass();
|
||||
|
@ -518,7 +518,8 @@ class java_lang_Throwable: AllStatic {
|
||||
trace_mirrors_offset = 2,
|
||||
trace_names_offset = 3,
|
||||
trace_next_offset = 4,
|
||||
trace_size = 5,
|
||||
trace_hidden_offset = 5,
|
||||
trace_size = 6,
|
||||
trace_chunk_size = 32
|
||||
};
|
||||
|
||||
@ -568,6 +569,8 @@ class java_lang_Throwable: AllStatic {
|
||||
static void java_printStackTrace(Handle throwable, TRAPS);
|
||||
// Debugging
|
||||
friend class JavaClasses;
|
||||
// Gets the method and bci of the top frame (TOS). Returns false if this failed.
|
||||
static bool get_top_method_and_bci(oop throwable, Method** method, int* bci);
|
||||
};
|
||||
|
||||
|
||||
|
@ -155,6 +155,7 @@ class GCTimer;
|
||||
do_klass(reflect_ConstantPool_klass, reflect_ConstantPool ) \
|
||||
do_klass(reflect_UnsafeStaticFieldAccessorImpl_klass, reflect_UnsafeStaticFieldAccessorImpl ) \
|
||||
do_klass(reflect_CallerSensitive_klass, reflect_CallerSensitive ) \
|
||||
do_klass(reflect_NativeConstructorAccessorImpl_klass, reflect_NativeConstructorAccessorImpl ) \
|
||||
\
|
||||
/* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \
|
||||
do_klass(DirectMethodHandle_klass, java_lang_invoke_DirectMethodHandle ) \
|
||||
|
@ -243,6 +243,7 @@
|
||||
template(reflect_Reflection, "jdk/internal/reflect/Reflection") \
|
||||
template(reflect_CallerSensitive, "jdk/internal/reflect/CallerSensitive") \
|
||||
template(reflect_CallerSensitive_signature, "Ljdk/internal/reflect/CallerSensitive;") \
|
||||
template(reflect_NativeConstructorAccessorImpl, "jdk/internal/reflect/NativeConstructorAccessorImpl")\
|
||||
template(checkedExceptions_name, "checkedExceptions") \
|
||||
template(clazz_name, "clazz") \
|
||||
template(exceptionTypes_name, "exceptionTypes") \
|
||||
|
@ -45,13 +45,25 @@ void EpsilonArguments::initialize() {
|
||||
FLAG_SET_DEFAULT(ExitOnOutOfMemoryError, true);
|
||||
}
|
||||
|
||||
// Warn users that non-resizable heap might be better for some configurations.
|
||||
// We are not adjusting the heap size by ourselves, because it affects startup time.
|
||||
if (InitialHeapSize != MaxHeapSize) {
|
||||
log_warning(gc)("Consider setting -Xms equal to -Xmx to avoid resizing hiccups");
|
||||
}
|
||||
|
||||
// Warn users that AlwaysPreTouch might be better for some configurations.
|
||||
// We are not turning this on by ourselves, because it affects startup time.
|
||||
if (FLAG_IS_DEFAULT(AlwaysPreTouch) && !AlwaysPreTouch) {
|
||||
log_warning(gc)("Consider enabling -XX:+AlwaysPreTouch to avoid memory commit hiccups");
|
||||
}
|
||||
|
||||
if (EpsilonMaxTLABSize < MinTLABSize) {
|
||||
warning("EpsilonMaxTLABSize < MinTLABSize, adjusting it to " SIZE_FORMAT, MinTLABSize);
|
||||
log_warning(gc)("EpsilonMaxTLABSize < MinTLABSize, adjusting it to " SIZE_FORMAT, MinTLABSize);
|
||||
EpsilonMaxTLABSize = MinTLABSize;
|
||||
}
|
||||
|
||||
if (!EpsilonElasticTLAB && EpsilonElasticTLABDecay) {
|
||||
warning("Disabling EpsilonElasticTLABDecay because EpsilonElasticTLAB is disabled");
|
||||
log_warning(gc)("Disabling EpsilonElasticTLABDecay because EpsilonElasticTLAB is disabled");
|
||||
FLAG_SET_DEFAULT(EpsilonElasticTLABDecay, false);
|
||||
}
|
||||
|
||||
|
@ -1630,7 +1630,6 @@ jint G1CollectedHeap::initialize_young_gen_sampling_thread() {
|
||||
}
|
||||
|
||||
jint G1CollectedHeap::initialize() {
|
||||
os::enable_vtime();
|
||||
|
||||
// Necessary to satisfy locking discipline assertions.
|
||||
|
||||
@ -4076,7 +4075,7 @@ private:
|
||||
Atomic::add(r->rem_set()->occupied_locked(), &_rs_length);
|
||||
|
||||
if (!is_young) {
|
||||
g1h->_hot_card_cache->reset_card_counts(r);
|
||||
g1h->hot_card_cache()->reset_card_counts(r);
|
||||
}
|
||||
|
||||
if (!evacuation_failed) {
|
||||
|
@ -129,7 +129,6 @@ class G1RegionMappingChangedListener : public G1MappingChangedListener {
|
||||
};
|
||||
|
||||
class G1CollectedHeap : public CollectedHeap {
|
||||
friend class G1FreeCollectionSetTask;
|
||||
friend class VM_CollectForMetadataAllocation;
|
||||
friend class VM_G1CollectForAllocation;
|
||||
friend class VM_G1CollectFull;
|
||||
@ -1138,7 +1137,7 @@ public:
|
||||
return _reserved.contains(addr);
|
||||
}
|
||||
|
||||
G1HotCardCache* g1_hot_card_cache() const { return _hot_card_cache; }
|
||||
G1HotCardCache* hot_card_cache() const { return _hot_card_cache; }
|
||||
|
||||
G1CardTable* card_table() const {
|
||||
return _card_table;
|
||||
|
@ -114,8 +114,9 @@ void G1FullGCPrepareTask::G1CalculatePointersClosure::reset_region_metadata(Heap
|
||||
hr->rem_set()->clear();
|
||||
hr->clear_cardtable();
|
||||
|
||||
if (_g1h->g1_hot_card_cache()->use_cache()) {
|
||||
_g1h->g1_hot_card_cache()->reset_card_counts(hr);
|
||||
G1HotCardCache* hcc = _g1h->hot_card_cache();
|
||||
if (hcc->use_cache()) {
|
||||
hcc->reset_card_counts(hr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -487,7 +487,7 @@ G1RemSet::G1RemSet(G1CollectedHeap* g1h,
|
||||
G1CardTable* ct,
|
||||
G1HotCardCache* hot_card_cache) :
|
||||
_scan_state(new G1RemSetScanState()),
|
||||
_prev_period_summary(),
|
||||
_prev_period_summary(false),
|
||||
_g1h(g1h),
|
||||
_ct(ct),
|
||||
_g1p(_g1h->policy()),
|
||||
@ -1404,7 +1404,7 @@ void G1RemSet::print_periodic_summary_info(const char* header, uint period_count
|
||||
if ((G1SummarizeRSetStatsPeriod > 0) && log_is_enabled(Trace, gc, remset) &&
|
||||
(period_count % G1SummarizeRSetStatsPeriod == 0)) {
|
||||
|
||||
G1RemSetSummary current(this);
|
||||
G1RemSetSummary current;
|
||||
_prev_period_summary.subtract_from(¤t);
|
||||
|
||||
Log(gc, remset) log;
|
||||
@ -1421,7 +1421,7 @@ void G1RemSet::print_summary_info() {
|
||||
Log(gc, remset, exit) log;
|
||||
if (log.is_trace()) {
|
||||
log.trace(" Cumulative RS summary");
|
||||
G1RemSetSummary current(this);
|
||||
G1RemSetSummary current;
|
||||
ResourceMark rm;
|
||||
LogStream ls(log.trace());
|
||||
current.print_on(&ls);
|
||||
|
@ -81,8 +81,7 @@ double G1RemSetSummary::rs_thread_vtime(uint thread) const {
|
||||
return _rs_threads_vtimes[thread];
|
||||
}
|
||||
|
||||
G1RemSetSummary::G1RemSetSummary() :
|
||||
_rem_set(NULL),
|
||||
G1RemSetSummary::G1RemSetSummary(bool should_update) :
|
||||
_total_mutator_refined_cards(0),
|
||||
_total_concurrent_refined_cards(0),
|
||||
_num_coarsenings(0),
|
||||
@ -91,17 +90,10 @@ G1RemSetSummary::G1RemSetSummary() :
|
||||
_sampling_thread_vtime(0.0f) {
|
||||
|
||||
memset(_rs_threads_vtimes, 0, sizeof(double) * _num_vtimes);
|
||||
}
|
||||
|
||||
G1RemSetSummary::G1RemSetSummary(G1RemSet* rem_set) :
|
||||
_rem_set(rem_set),
|
||||
_total_mutator_refined_cards(0),
|
||||
_total_concurrent_refined_cards(0),
|
||||
_num_coarsenings(0),
|
||||
_num_vtimes(G1ConcurrentRefine::max_num_threads()),
|
||||
_rs_threads_vtimes(NEW_C_HEAP_ARRAY(double, _num_vtimes, mtGC)),
|
||||
_sampling_thread_vtime(0.0f) {
|
||||
update();
|
||||
if (should_update) {
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
G1RemSetSummary::~G1RemSetSummary() {
|
||||
|
@ -36,8 +36,6 @@ class G1RemSetSummary {
|
||||
private:
|
||||
friend class GetRSThreadVTimeClosure;
|
||||
|
||||
G1RemSet* _rem_set;
|
||||
|
||||
size_t _total_mutator_refined_cards;
|
||||
size_t _total_concurrent_refined_cards;
|
||||
|
||||
@ -57,8 +55,7 @@ private:
|
||||
void update();
|
||||
|
||||
public:
|
||||
G1RemSetSummary();
|
||||
G1RemSetSummary(G1RemSet* remset);
|
||||
G1RemSetSummary(bool should_update = true);
|
||||
|
||||
~G1RemSetSummary();
|
||||
|
||||
|
@ -268,17 +268,12 @@ oop ShenandoahBarrierSet::oop_load_from_native_barrier(oop obj) {
|
||||
}
|
||||
|
||||
ShenandoahMarkingContext* const marking_context = _heap->marking_context();
|
||||
|
||||
if (_heap->is_evacuation_in_progress()) {
|
||||
// Normal GC
|
||||
if (!marking_context->is_marked(obj)) {
|
||||
return NULL;
|
||||
}
|
||||
} else if (_heap->is_concurrent_traversal_in_progress()) {
|
||||
// Traversal GC
|
||||
if (marking_context->is_complete() &&
|
||||
!marking_context->is_marked(resolve_forwarded_not_null(obj))) {
|
||||
if (_heap->is_evacuation_in_progress() && !marking_context->is_marked(obj)) {
|
||||
Thread* thr = Thread::current();
|
||||
if (thr->is_Java_thread()) {
|
||||
return NULL;
|
||||
} else {
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
class ShenandoahHeap;
|
||||
class ShenandoahMarkingContext;
|
||||
class ShenandoahHeapRegionSet;
|
||||
class Thread;
|
||||
|
||||
class ShenandoahForwardedIsAliveClosure: public BoolObjectClosure {
|
||||
@ -65,6 +66,20 @@ private:
|
||||
inline void do_oop_work(T* p);
|
||||
};
|
||||
|
||||
class ShenandoahTraversalUpdateRefsClosure: public OopClosure {
|
||||
private:
|
||||
ShenandoahHeap* const _heap;
|
||||
ShenandoahHeapRegionSet* const _traversal_set;
|
||||
|
||||
public:
|
||||
inline ShenandoahTraversalUpdateRefsClosure();
|
||||
inline void do_oop(oop* p);
|
||||
inline void do_oop(narrowOop* p);
|
||||
private:
|
||||
template <class T>
|
||||
inline void do_oop_work(T* p);
|
||||
};
|
||||
|
||||
class ShenandoahEvacuateUpdateRootsClosure: public BasicOopIterateClosure {
|
||||
private:
|
||||
ShenandoahHeap* _heap;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "gc/shenandoah/shenandoahAsserts.hpp"
|
||||
#include "gc/shenandoah/shenandoahClosures.hpp"
|
||||
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
|
||||
#include "gc/shenandoah/shenandoahTraversalGC.hpp"
|
||||
#include "oops/compressedOops.inline.hpp"
|
||||
#include "runtime/thread.hpp"
|
||||
|
||||
@ -78,6 +79,29 @@ void ShenandoahUpdateRefsClosure::do_oop_work(T* p) {
|
||||
void ShenandoahUpdateRefsClosure::do_oop(oop* p) { do_oop_work(p); }
|
||||
void ShenandoahUpdateRefsClosure::do_oop(narrowOop* p) { do_oop_work(p); }
|
||||
|
||||
ShenandoahTraversalUpdateRefsClosure::ShenandoahTraversalUpdateRefsClosure() :
|
||||
_heap(ShenandoahHeap::heap()),
|
||||
_traversal_set(ShenandoahHeap::heap()->traversal_gc()->traversal_set()) {
|
||||
assert(_heap->is_traversal_mode(), "Why we here?");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void ShenandoahTraversalUpdateRefsClosure::do_oop_work(T* p) {
|
||||
T o = RawAccess<>::oop_load(p);
|
||||
if (!CompressedOops::is_null(o)) {
|
||||
oop obj = CompressedOops::decode_not_null(o);
|
||||
if (_heap->in_collection_set(obj) || _traversal_set->is_in((HeapWord*)obj)) {
|
||||
obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
|
||||
RawAccess<IS_NOT_NULL>::oop_store(p, obj);
|
||||
} else {
|
||||
shenandoah_assert_not_forwarded(p, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShenandoahTraversalUpdateRefsClosure::do_oop(oop* p) { do_oop_work(p); }
|
||||
void ShenandoahTraversalUpdateRefsClosure::do_oop(narrowOop* p) { do_oop_work(p); }
|
||||
|
||||
ShenandoahEvacuateUpdateRootsClosure::ShenandoahEvacuateUpdateRootsClosure() :
|
||||
_heap(ShenandoahHeap::heap()), _thread(Thread::current()) {
|
||||
}
|
||||
|
@ -319,13 +319,20 @@ public:
|
||||
};
|
||||
|
||||
void ShenandoahConcurrentMark::update_thread_roots(ShenandoahPhaseTimings::Phase root_phase) {
|
||||
WorkGang* workers = _heap->workers();
|
||||
bool is_par = workers->active_workers() > 1;
|
||||
assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint");
|
||||
|
||||
ShenandoahGCPhase phase(root_phase);
|
||||
|
||||
#if COMPILER2_OR_JVMCI
|
||||
DerivedPointerTable::clear();
|
||||
#endif
|
||||
|
||||
WorkGang* workers = _heap->workers();
|
||||
bool is_par = workers->active_workers() > 1;
|
||||
|
||||
ShenandoahUpdateThreadRootsTask task(is_par, root_phase);
|
||||
workers->run_task(&task);
|
||||
|
||||
#if COMPILER2_OR_JVMCI
|
||||
DerivedPointerTable::update_pointers();
|
||||
#endif
|
||||
|
@ -1493,31 +1493,36 @@ void ShenandoahHeap::op_final_mark() {
|
||||
|
||||
stop_concurrent_marking();
|
||||
|
||||
// All allocations past TAMS are implicitly live, adjust the region data.
|
||||
// Bitmaps/TAMS are swapped at this point, so we need to poll complete bitmap.
|
||||
{
|
||||
ShenandoahGCPhase phase(ShenandoahPhaseTimings::complete_liveness);
|
||||
|
||||
// All allocations past TAMS are implicitly live, adjust the region data.
|
||||
// Bitmaps/TAMS are swapped at this point, so we need to poll complete bitmap.
|
||||
ShenandoahCompleteLivenessClosure cl;
|
||||
parallel_heap_region_iterate(&cl);
|
||||
}
|
||||
|
||||
// Force the threads to reacquire their TLABs outside the collection set.
|
||||
{
|
||||
ShenandoahGCPhase prepare_evac(ShenandoahPhaseTimings::prepare_evac);
|
||||
|
||||
ShenandoahGCPhase phase(ShenandoahPhaseTimings::retire_tlabs);
|
||||
make_parsable(true);
|
||||
}
|
||||
|
||||
// Trash the collection set left over from previous cycle, if any.
|
||||
{
|
||||
ShenandoahGCPhase phase(ShenandoahPhaseTimings::trash_cset);
|
||||
trash_cset_regions();
|
||||
}
|
||||
|
||||
{
|
||||
ShenandoahHeapLocker locker(lock());
|
||||
_collection_set->clear();
|
||||
_free_set->clear();
|
||||
{
|
||||
ShenandoahGCPhase phase(ShenandoahPhaseTimings::prepare_evac);
|
||||
|
||||
heuristics()->choose_collection_set(_collection_set);
|
||||
ShenandoahHeapLocker locker(lock());
|
||||
_collection_set->clear();
|
||||
_free_set->clear();
|
||||
|
||||
_free_set->rebuild();
|
||||
}
|
||||
heuristics()->choose_collection_set(_collection_set);
|
||||
|
||||
_free_set->rebuild();
|
||||
}
|
||||
|
||||
// If collection set has candidates, start evacuation.
|
||||
@ -1580,7 +1585,10 @@ void ShenandoahHeap::op_final_evac() {
|
||||
|
||||
set_evacuation_in_progress(false);
|
||||
|
||||
retire_and_reset_gclabs();
|
||||
{
|
||||
ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_evac_retire_gclabs);
|
||||
retire_and_reset_gclabs();
|
||||
}
|
||||
|
||||
if (ShenandoahVerify) {
|
||||
verifier()->verify_after_evacuation();
|
||||
@ -1902,7 +1910,7 @@ void ShenandoahHeap::set_concurrent_mark_in_progress(bool in_progress) {
|
||||
}
|
||||
|
||||
void ShenandoahHeap::set_concurrent_traversal_in_progress(bool in_progress) {
|
||||
set_gc_state_mask(TRAVERSAL | HAS_FORWARDED | UPDATEREFS, in_progress);
|
||||
set_gc_state_mask(TRAVERSAL, in_progress);
|
||||
ShenandoahBarrierSet::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress);
|
||||
}
|
||||
|
||||
@ -2034,11 +2042,19 @@ void ShenandoahHeap::stw_process_weak_roots(bool full_gc) {
|
||||
// Cleanup weak roots
|
||||
ShenandoahGCPhase phase(timing_phase);
|
||||
if (has_forwarded_objects()) {
|
||||
ShenandoahForwardedIsAliveClosure is_alive;
|
||||
ShenandoahUpdateRefsClosure keep_alive;
|
||||
ShenandoahParallelWeakRootsCleaningTask<ShenandoahForwardedIsAliveClosure, ShenandoahUpdateRefsClosure>
|
||||
cleaning_task(&is_alive, &keep_alive, num_workers);
|
||||
_workers->run_task(&cleaning_task);
|
||||
if (is_traversal_mode()) {
|
||||
ShenandoahForwardedIsAliveClosure is_alive;
|
||||
ShenandoahTraversalUpdateRefsClosure keep_alive;
|
||||
ShenandoahParallelWeakRootsCleaningTask<ShenandoahForwardedIsAliveClosure, ShenandoahTraversalUpdateRefsClosure>
|
||||
cleaning_task(&is_alive, &keep_alive, num_workers);
|
||||
_workers->run_task(&cleaning_task);
|
||||
} else {
|
||||
ShenandoahForwardedIsAliveClosure is_alive;
|
||||
ShenandoahUpdateRefsClosure keep_alive;
|
||||
ShenandoahParallelWeakRootsCleaningTask<ShenandoahForwardedIsAliveClosure, ShenandoahUpdateRefsClosure>
|
||||
cleaning_task(&is_alive, &keep_alive, num_workers);
|
||||
_workers->run_task(&cleaning_task);
|
||||
}
|
||||
} else {
|
||||
ShenandoahIsAliveClosure is_alive;
|
||||
#ifdef ASSERT
|
||||
@ -2060,7 +2076,12 @@ void ShenandoahHeap::parallel_cleaning(bool full_gc) {
|
||||
}
|
||||
|
||||
void ShenandoahHeap::set_has_forwarded_objects(bool cond) {
|
||||
set_gc_state_mask(HAS_FORWARDED, cond);
|
||||
if (is_traversal_mode()) {
|
||||
set_gc_state_mask(HAS_FORWARDED | UPDATEREFS, cond);
|
||||
} else {
|
||||
set_gc_state_mask(HAS_FORWARDED, cond);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ShenandoahHeap::set_process_references(bool pr) {
|
||||
@ -2229,7 +2250,10 @@ void ShenandoahHeap::op_init_updaterefs() {
|
||||
|
||||
set_evacuation_in_progress(false);
|
||||
|
||||
retire_and_reset_gclabs();
|
||||
{
|
||||
ShenandoahGCPhase phase(ShenandoahPhaseTimings::init_update_refs_retire_gclabs);
|
||||
retire_and_reset_gclabs();
|
||||
}
|
||||
|
||||
if (ShenandoahVerify) {
|
||||
if (!is_degenerated_gc_in_progress()) {
|
||||
@ -2239,14 +2263,19 @@ void ShenandoahHeap::op_init_updaterefs() {
|
||||
}
|
||||
|
||||
set_update_refs_in_progress(true);
|
||||
make_parsable(true);
|
||||
for (uint i = 0; i < num_regions(); i++) {
|
||||
ShenandoahHeapRegion* r = get_region(i);
|
||||
r->set_concurrent_iteration_safe_limit(r->top());
|
||||
}
|
||||
|
||||
// Reset iterator.
|
||||
_update_refs_iterator.reset();
|
||||
{
|
||||
ShenandoahGCPhase phase(ShenandoahPhaseTimings::init_update_refs_prepare);
|
||||
|
||||
make_parsable(true);
|
||||
for (uint i = 0; i < num_regions(); i++) {
|
||||
ShenandoahHeapRegion* r = get_region(i);
|
||||
r->set_concurrent_iteration_safe_limit(r->top());
|
||||
}
|
||||
|
||||
// Reset iterator.
|
||||
_update_refs_iterator.reset();
|
||||
}
|
||||
|
||||
if (ShenandoahPacing) {
|
||||
pacer()->setup_for_updaterefs();
|
||||
@ -2258,7 +2287,7 @@ void ShenandoahHeap::op_final_updaterefs() {
|
||||
|
||||
// Check if there is left-over work, and finish it
|
||||
if (_update_refs_iterator.has_next()) {
|
||||
ShenandoahGCPhase final_work(ShenandoahPhaseTimings::final_update_refs_finish_work);
|
||||
ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_update_refs_finish_work);
|
||||
|
||||
// Finish updating references where we left off.
|
||||
clear_cancelled_gc();
|
||||
@ -2287,9 +2316,11 @@ void ShenandoahHeap::op_final_updaterefs() {
|
||||
verifier()->verify_roots_in_to_space();
|
||||
}
|
||||
|
||||
ShenandoahGCPhase final_update_refs(ShenandoahPhaseTimings::final_update_refs_recycle);
|
||||
{
|
||||
ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_update_refs_trash_cset);
|
||||
trash_cset_regions();
|
||||
}
|
||||
|
||||
trash_cset_regions();
|
||||
set_has_forwarded_objects(false);
|
||||
set_update_refs_in_progress(false);
|
||||
|
||||
|
@ -41,6 +41,9 @@ public:
|
||||
ShenandoahLock() : _state(unlocked), _owner(NULL) {};
|
||||
|
||||
void lock() {
|
||||
#ifdef ASSERT
|
||||
assert(_owner != Thread::current(), "reentrant locking attempt, would deadlock");
|
||||
#endif
|
||||
Thread::SpinAcquire(&_state, "Shenandoah Heap Lock");
|
||||
#ifdef ASSERT
|
||||
assert(_state == locked, "must be locked");
|
||||
|
@ -100,8 +100,9 @@ class outputStream;
|
||||
f(purge_par, " Parallel Cleanup") \
|
||||
f(purge_cldg, " CLDG") \
|
||||
f(complete_liveness, " Complete Liveness") \
|
||||
f(retire_tlabs, " Retire TLABs") \
|
||||
f(trash_cset, " Trash CSet") \
|
||||
f(prepare_evac, " Prepare Evacuation") \
|
||||
f(recycle_regions, " Recycle regions") \
|
||||
\
|
||||
/* Per-thread timer block, should have "roots" counters in consistent order */ \
|
||||
f(init_evac, " Initial Evacuation") \
|
||||
@ -127,9 +128,12 @@ class outputStream;
|
||||
\
|
||||
f(final_evac_gross, "Pause Final Evac (G)") \
|
||||
f(final_evac, "Pause Final Evac (N)") \
|
||||
f(final_evac_retire_gclabs, " Retire GCLABs") \
|
||||
\
|
||||
f(init_update_refs_gross, "Pause Init Update Refs (G)") \
|
||||
f(init_update_refs, "Pause Init Update Refs (N)") \
|
||||
f(init_update_refs_retire_gclabs, " Retire GCLABs") \
|
||||
f(init_update_refs_prepare, " Prepare") \
|
||||
\
|
||||
f(final_update_refs_gross, "Pause Final Update Refs (G)") \
|
||||
f(final_update_refs, "Pause Final Update Refs (N)") \
|
||||
@ -157,7 +161,7 @@ class outputStream;
|
||||
f(final_update_refs_string_dedup_queue_roots, " UR: Dedup Queue Roots") \
|
||||
f(final_update_refs_finish_queues, " UR: Finish Queues") \
|
||||
\
|
||||
f(final_update_refs_recycle, " Recycle") \
|
||||
f(final_update_refs_trash_cset, " Trash CSet") \
|
||||
\
|
||||
f(degen_gc_gross, "Pause Degenerated GC (G)") \
|
||||
f(degen_gc, "Pause Degenerated GC (N)") \
|
||||
|
@ -189,6 +189,18 @@ ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimi
|
||||
_thread_roots(n_workers > 1) {
|
||||
}
|
||||
|
||||
void ShenandoahRootUpdater::strong_roots_do(uint worker_id, OopClosure* oops_cl) {
|
||||
CodeBlobToOopClosure update_blobs(oops_cl, CodeBlobToOopClosure::FixRelocations);
|
||||
CLDToOopClosure clds(oops_cl, ClassLoaderData::_claim_strong);
|
||||
|
||||
_serial_roots.oops_do(oops_cl, worker_id);
|
||||
_vm_roots.oops_do(oops_cl, worker_id);
|
||||
|
||||
_thread_roots.oops_do(oops_cl, NULL, worker_id);
|
||||
_cld_roots.cld_do(&clds, worker_id);
|
||||
_code_roots.code_blobs_do(&update_blobs, worker_id);
|
||||
}
|
||||
|
||||
ShenandoahRootAdjuster::ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
|
||||
ShenandoahRootProcessor(phase),
|
||||
_thread_roots(n_workers > 1) {
|
||||
|
@ -304,6 +304,8 @@ public:
|
||||
|
||||
template<typename IsAlive, typename KeepAlive>
|
||||
void roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive);
|
||||
|
||||
void strong_roots_do(uint worker_id, OopClosure* oops_cl);
|
||||
};
|
||||
|
||||
// Adjuster all roots at a safepoint during full gc
|
||||
|
@ -390,6 +390,7 @@ void ShenandoahTraversalGC::init_traversal_collection() {
|
||||
}
|
||||
|
||||
_heap->set_concurrent_traversal_in_progress(true);
|
||||
_heap->set_has_forwarded_objects(true);
|
||||
|
||||
bool process_refs = _heap->process_references();
|
||||
if (process_refs) {
|
||||
@ -601,11 +602,14 @@ void ShenandoahTraversalGC::final_traversal_collection() {
|
||||
TASKQUEUE_STATS_ONLY(_task_queues->reset_taskqueue_stats());
|
||||
|
||||
// No more marking expected
|
||||
_heap->set_concurrent_traversal_in_progress(false);
|
||||
_heap->mark_complete_marking_context();
|
||||
|
||||
fixup_roots();
|
||||
_heap->parallel_cleaning(false);
|
||||
|
||||
_heap->set_has_forwarded_objects(false);
|
||||
|
||||
// Resize metaspace
|
||||
MetaspaceGC::compute_new_size();
|
||||
|
||||
@ -651,7 +655,6 @@ void ShenandoahTraversalGC::final_traversal_collection() {
|
||||
}
|
||||
|
||||
assert(_task_queues->is_empty(), "queues must be empty after traversal GC");
|
||||
_heap->set_concurrent_traversal_in_progress(false);
|
||||
assert(!_heap->cancelled_gc(), "must not be cancelled when getting out here");
|
||||
|
||||
if (ShenandoahVerify) {
|
||||
@ -697,8 +700,7 @@ public:
|
||||
void work(uint worker_id) {
|
||||
ShenandoahParallelWorkerSession worker_session(worker_id);
|
||||
ShenandoahTraversalFixRootsClosure cl;
|
||||
ShenandoahForwardedIsAliveClosure is_alive;
|
||||
_rp->roots_do<ShenandoahForwardedIsAliveClosure, ShenandoahTraversalFixRootsClosure>(worker_id, &is_alive, &cl);
|
||||
_rp->strong_roots_do(worker_id, &cl);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -191,6 +191,13 @@ JVM_InitStackTraceElementArray(JNIEnv *env, jobjectArray elements, jobject throw
|
||||
JNIEXPORT void JNICALL
|
||||
JVM_InitStackTraceElement(JNIEnv* env, jobject element, jobject stackFrameInfo);
|
||||
|
||||
/*
|
||||
* java.lang.NullPointerException
|
||||
*/
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
JVM_GetExtendedNPEMessage(JNIEnv *env, jthrowable throwable);
|
||||
|
||||
/*
|
||||
* java.lang.StackWalker
|
||||
*/
|
||||
|
1481
src/hotspot/share/interpreter/bytecodeUtils.cpp
Normal file
1481
src/hotspot/share/interpreter/bytecodeUtils.cpp
Normal file
File diff suppressed because it is too large
Load Diff
41
src/hotspot/share/interpreter/bytecodeUtils.hpp
Normal file
41
src/hotspot/share/interpreter/bytecodeUtils.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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_INTERPRETER_BYTECODEUTILS_HPP
|
||||
#define SHARE_INTERPRETER_BYTECODEUTILS_HPP
|
||||
|
||||
#include "memory/allocation.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
class Method;
|
||||
class outputStream;
|
||||
|
||||
class BytecodeUtils : public AllStatic {
|
||||
public:
|
||||
// NPE extended message. Return true if string is printed.
|
||||
static bool get_NPE_message_at(outputStream* ss, Method* method, int bci);
|
||||
};
|
||||
|
||||
#endif // SHARE_INTERPRETER_BYTECODEUTILS_HPP
|
@ -2497,10 +2497,18 @@ void InstanceKlass::unload_class(InstanceKlass* ik) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static void method_release_C_heap_structures(Method* m) {
|
||||
m->release_C_heap_structures();
|
||||
}
|
||||
|
||||
void InstanceKlass::release_C_heap_structures(InstanceKlass* ik) {
|
||||
// Clean up C heap
|
||||
ik->release_C_heap_structures();
|
||||
ik->constants()->release_C_heap_structures();
|
||||
|
||||
// Deallocate and call destructors for MDO mutexes
|
||||
ik->methods_do(method_release_C_heap_structures);
|
||||
|
||||
}
|
||||
|
||||
void InstanceKlass::release_C_heap_structures() {
|
||||
|
@ -118,11 +118,6 @@ Method::Method(ConstMethod* xconst, AccessFlags access_flags) {
|
||||
void Method::deallocate_contents(ClassLoaderData* loader_data) {
|
||||
MetadataFactory::free_metadata(loader_data, constMethod());
|
||||
set_constMethod(NULL);
|
||||
#if INCLUDE_JVMCI
|
||||
if (method_data()) {
|
||||
FailedSpeculation::free_failed_speculations(method_data()->get_failed_speculations_address());
|
||||
}
|
||||
#endif
|
||||
MetadataFactory::free_metadata(loader_data, method_data());
|
||||
set_method_data(NULL);
|
||||
MetadataFactory::free_metadata(loader_data, method_counters());
|
||||
@ -131,6 +126,16 @@ void Method::deallocate_contents(ClassLoaderData* loader_data) {
|
||||
if (code() != NULL) _code = NULL;
|
||||
}
|
||||
|
||||
void Method::release_C_heap_structures() {
|
||||
if (method_data()) {
|
||||
#if INCLUDE_JVMCI
|
||||
FailedSpeculation::free_failed_speculations(method_data()->get_failed_speculations_address());
|
||||
#endif
|
||||
// Destroy MethodData
|
||||
method_data()->~MethodData();
|
||||
}
|
||||
}
|
||||
|
||||
address Method::get_i2c_entry() {
|
||||
assert(adapter() != NULL, "must have");
|
||||
return adapter()->get_i2c_entry();
|
||||
|
@ -1006,6 +1006,8 @@ public:
|
||||
// Deallocation function for redefine classes or if an error occurs
|
||||
void deallocate_contents(ClassLoaderData* loader_data);
|
||||
|
||||
void release_C_heap_structures();
|
||||
|
||||
Method* get_new_method() const {
|
||||
InstanceKlass* holder = method_holder();
|
||||
Method* new_method = holder->method_with_idnum(orig_method_idnum());
|
||||
|
@ -2445,7 +2445,7 @@ public:
|
||||
virtual void metaspace_pointers_do(MetaspaceClosure* iter);
|
||||
virtual MetaspaceObj::Type type() const { return MethodDataType; }
|
||||
|
||||
// Deallocation support - no pointer fields to deallocate
|
||||
// Deallocation support - no metaspace pointer fields to deallocate
|
||||
void deallocate_contents(ClassLoaderData* loader_data) {}
|
||||
|
||||
// GC support
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "classfile/vmSymbols.hpp"
|
||||
#include "gc/shared/collectedHeap.inline.hpp"
|
||||
#include "interpreter/bytecode.hpp"
|
||||
#include "interpreter/bytecodeUtils.hpp"
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "memory/heapShared.hpp"
|
||||
@ -531,13 +532,37 @@ JVM_END
|
||||
|
||||
// java.lang.Throwable //////////////////////////////////////////////////////
|
||||
|
||||
|
||||
JVM_ENTRY(void, JVM_FillInStackTrace(JNIEnv *env, jobject receiver))
|
||||
JVMWrapper("JVM_FillInStackTrace");
|
||||
Handle exception(thread, JNIHandles::resolve_non_null(receiver));
|
||||
java_lang_Throwable::fill_in_stack_trace(exception);
|
||||
JVM_END
|
||||
|
||||
// java.lang.NullPointerException ///////////////////////////////////////////
|
||||
|
||||
JVM_ENTRY(jstring, JVM_GetExtendedNPEMessage(JNIEnv *env, jthrowable throwable))
|
||||
if (!ShowCodeDetailsInExceptionMessages) return NULL;
|
||||
|
||||
oop exc = JNIHandles::resolve_non_null(throwable);
|
||||
|
||||
Method* method;
|
||||
int bci;
|
||||
if (!java_lang_Throwable::get_top_method_and_bci(exc, &method, &bci)) {
|
||||
return NULL;
|
||||
}
|
||||
if (method->is_native()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stringStream ss;
|
||||
bool ok = BytecodeUtils::get_NPE_message_at(&ss, method, bci);
|
||||
if (ok) {
|
||||
oop result = java_lang_String::create_oop_from_str(ss.base(), CHECK_0);
|
||||
return (jstring) JNIHandles::make_local(env, result);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
JVM_END
|
||||
|
||||
// java.lang.StackTraceElement //////////////////////////////////////////////
|
||||
|
||||
|
@ -295,7 +295,7 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
|
||||
|
||||
// Reallocate the non-escaping objects and restore their fields. Then
|
||||
// relock objects if synchronization on them was eliminated.
|
||||
if (jvmci_enabled || ((DoEscapeAnalysis || EliminateNestedLocks) && EliminateAllocations)) {
|
||||
if (jvmci_enabled || (DoEscapeAnalysis && EliminateAllocations)) {
|
||||
realloc_failures = eliminate_allocations(thread, exec_mode, cm, deoptee, map, chunk);
|
||||
}
|
||||
#endif // COMPILER2_OR_JVMCI
|
||||
|
@ -643,6 +643,10 @@ const size_t minimumSymbolTableSize = 1024;
|
||||
product(bool, OmitStackTraceInFastThrow, true, \
|
||||
"Omit backtraces for some 'hot' exceptions in optimized code") \
|
||||
\
|
||||
manageable(bool, ShowCodeDetailsInExceptionMessages, false, \
|
||||
"Show exception messages from RuntimeExceptions that contain " \
|
||||
"snippets of the failing code. Disable this to improve privacy.") \
|
||||
\
|
||||
product(bool, PrintWarnings, true, \
|
||||
"Print JVM warnings to output stream") \
|
||||
\
|
||||
|
@ -47,8 +47,6 @@ class frame;
|
||||
// OS services (time, I/O) as well as other functionality with system-
|
||||
// dependent code.
|
||||
|
||||
typedef void (*dll_func)(...);
|
||||
|
||||
class Thread;
|
||||
class JavaThread;
|
||||
class NativeCallStack;
|
||||
@ -195,14 +193,9 @@ class os: AllStatic {
|
||||
|
||||
// The "virtual time" of a thread is the amount of time a thread has
|
||||
// actually run. The first function indicates whether the OS supports
|
||||
// this functionality for the current thread, and if so:
|
||||
// * the second enables vtime tracking (if that is required).
|
||||
// * the third tells whether vtime is enabled.
|
||||
// * the fourth returns the elapsed virtual time for the current
|
||||
// thread.
|
||||
// this functionality for the current thread, and if so the second
|
||||
// returns the elapsed virtual time for the current thread.
|
||||
static bool supports_vtime();
|
||||
static bool enable_vtime();
|
||||
static bool vtime_enabled();
|
||||
static double elapsedVTime();
|
||||
|
||||
// Return current local time in a string (YYYY-MM-DD HH:MM:SS).
|
||||
@ -254,14 +247,6 @@ class os: AllStatic {
|
||||
return _initial_active_processor_count;
|
||||
}
|
||||
|
||||
// Bind processes to processors.
|
||||
// This is a two step procedure:
|
||||
// first you generate a distribution of processes to processors,
|
||||
// then you bind processes according to that distribution.
|
||||
// Compute a distribution for number of processes to processors.
|
||||
// Stores the processor id's into the distribution array argument.
|
||||
// Returns true if it worked, false if it didn't.
|
||||
static bool distribute_processes(uint length, uint* distribution);
|
||||
// Binds the current process to a processor.
|
||||
// Returns true if it worked, false if it didn't.
|
||||
static bool bind_to_processor(uint processor_id);
|
||||
@ -496,7 +481,6 @@ class os: AllStatic {
|
||||
static void verify_stack_alignment() PRODUCT_RETURN;
|
||||
|
||||
static bool message_box(const char* title, const char* message);
|
||||
static char* do_you_want_to_debug(const char* message);
|
||||
|
||||
// run cmd in a separate process and return its exit code; or -1 on failures
|
||||
static int fork_and_exec(char *cmd, bool use_vfork_if_available = false);
|
||||
@ -520,7 +504,6 @@ class os: AllStatic {
|
||||
static void die();
|
||||
|
||||
// File i/o operations
|
||||
static const int default_file_open_flags();
|
||||
static int open(const char *path, int oflag, int mode);
|
||||
static FILE* open(int fd, const char* mode);
|
||||
static FILE* fopen(const char* path, const char* mode);
|
||||
@ -668,9 +651,6 @@ class os: AllStatic {
|
||||
// Will not change the value of errno.
|
||||
static const char* errno_name(int e);
|
||||
|
||||
// Determines whether the calling process is being debugged by a user-mode debugger.
|
||||
static bool is_debugger_attached();
|
||||
|
||||
// wait for a key press if PauseAtExit is set
|
||||
static void wait_for_keypress_at_exit(void);
|
||||
|
||||
@ -966,10 +946,6 @@ class os: AllStatic {
|
||||
return _state == SR_RUNNING;
|
||||
}
|
||||
|
||||
bool is_suspend_request() const {
|
||||
return _state == SR_SUSPEND_REQUEST;
|
||||
}
|
||||
|
||||
bool is_suspended() const {
|
||||
return _state == SR_SUSPENDED;
|
||||
}
|
||||
|
@ -151,7 +151,13 @@ template <> void DCmdArgument<bool>::parse_value(const char* str,
|
||||
ResourceMark rm;
|
||||
|
||||
char* buf = NEW_RESOURCE_ARRAY(char, len + 1);
|
||||
|
||||
PRAGMA_DIAG_PUSH
|
||||
PRAGMA_STRINGOP_TRUNCATION_IGNORED
|
||||
// This code can incorrectly cause a "stringop-truncation" warning with gcc
|
||||
strncpy(buf, str, len);
|
||||
PRAGMA_DIAG_POP
|
||||
|
||||
buf[len] = '\0';
|
||||
Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IllegalArgumentException(),
|
||||
"Boolean parsing error in command argument '%s'. Could not parse: %s.\n", _name, buf);
|
||||
|
@ -62,4 +62,8 @@
|
||||
#define PRAGMA_FORMAT_IGNORED
|
||||
#endif
|
||||
|
||||
#ifndef PRAGMA_STRINGOP_TRUNCATION_IGNORED
|
||||
#define PRAGMA_STRINGOP_TRUNCATION_IGNORED
|
||||
#endif
|
||||
|
||||
#endif // SHARE_UTILITIES_COMPILERWARNINGS_HPP
|
||||
|
@ -50,6 +50,12 @@
|
||||
|
||||
#define PRAGMA_FORMAT_IGNORED PRAGMA_DISABLE_GCC_WARNING("-Wformat")
|
||||
|
||||
// Disable -Wstringop-truncation which is introduced in GCC 8.
|
||||
// https://gcc.gnu.org/gcc-8/changes.html
|
||||
#if !defined(__clang_major__) && (__GNUC__ >= 8)
|
||||
#define PRAGMA_STRINGOP_TRUNCATION_IGNORED PRAGMA_DISABLE_GCC_WARNING("-Wstringop-truncation")
|
||||
#endif
|
||||
|
||||
#if defined(__clang_major__) && \
|
||||
(__clang_major__ >= 4 || \
|
||||
(__clang_major__ >= 3 && __clang_minor__ >= 1)) || \
|
||||
|
@ -367,12 +367,22 @@ public final class FilePermission extends Permission implements Serializable {
|
||||
this.mask = mask;
|
||||
|
||||
if (cpath.equals("<<ALL FILES>>")) {
|
||||
allFiles = true;
|
||||
directory = true;
|
||||
recursive = true;
|
||||
cpath = "";
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate path by platform's default file system
|
||||
try {
|
||||
String name = cpath.endsWith("*") ? cpath.substring(0, cpath.length() - 1) + "-" : cpath;
|
||||
builtInFS.getPath(new File(name).getPath());
|
||||
} catch (InvalidPathException ipe) {
|
||||
invalid = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// store only the canonical cpath if possible
|
||||
cpath = AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||
public String run() {
|
||||
@ -463,13 +473,16 @@ public final class FilePermission extends Permission implements Serializable {
|
||||
* <P>
|
||||
* The default value of the {@code jdk.io.permissionsUseCanonicalPath}
|
||||
* system property is {@code false} in this implementation.
|
||||
* <p>
|
||||
* The value can also be set with a security property using the same name,
|
||||
* but setting a system property will override the security property value.
|
||||
*
|
||||
* @param path the pathname of the file/directory.
|
||||
* @param actions the action string.
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If actions is {@code null}, empty or contains an action
|
||||
* other than the specified possible actions.
|
||||
* @throws IllegalArgumentException if actions is {@code null}, empty,
|
||||
* malformed or contains an action other than the specified
|
||||
* possible actions
|
||||
*/
|
||||
public FilePermission(String path, String actions) {
|
||||
super(path);
|
||||
@ -573,19 +586,19 @@ public final class FilePermission extends Permission implements Serializable {
|
||||
* @return the effective mask
|
||||
*/
|
||||
boolean impliesIgnoreMask(FilePermission that) {
|
||||
if (this == that) {
|
||||
return true;
|
||||
}
|
||||
if (allFiles) {
|
||||
return true;
|
||||
}
|
||||
if (this.invalid || that.invalid) {
|
||||
return false;
|
||||
}
|
||||
if (that.allFiles) {
|
||||
return false;
|
||||
}
|
||||
if (FilePermCompat.nb) {
|
||||
if (this == that) {
|
||||
return true;
|
||||
}
|
||||
if (allFiles) {
|
||||
return true;
|
||||
}
|
||||
if (this.invalid || that.invalid) {
|
||||
return false;
|
||||
}
|
||||
if (that.allFiles) {
|
||||
return false;
|
||||
}
|
||||
// Left at least same level of wildness as right
|
||||
if ((this.recursive && that.recursive) != that.recursive
|
||||
|| (this.directory && that.directory) != that.directory) {
|
||||
@ -783,10 +796,10 @@ public final class FilePermission extends Permission implements Serializable {
|
||||
|
||||
FilePermission that = (FilePermission) obj;
|
||||
|
||||
if (this.invalid || that.invalid) {
|
||||
return false;
|
||||
}
|
||||
if (FilePermCompat.nb) {
|
||||
if (this.invalid || that.invalid) {
|
||||
return false;
|
||||
}
|
||||
return (this.mask == that.mask) &&
|
||||
(this.allFiles == that.allFiles) &&
|
||||
this.npath.equals(that.npath) &&
|
||||
@ -795,6 +808,7 @@ public final class FilePermission extends Permission implements Serializable {
|
||||
(this.recursive == that.recursive);
|
||||
} else {
|
||||
return (this.mask == that.mask) &&
|
||||
(this.allFiles == that.allFiles) &&
|
||||
this.cpath.equals(that.cpath) &&
|
||||
(this.directory == that.directory) &&
|
||||
(this.recursive == that.recursive);
|
||||
@ -921,17 +935,18 @@ public final class FilePermission extends Permission implements Serializable {
|
||||
}
|
||||
|
||||
// make sure we didn't just match the tail of a word
|
||||
// like "ackbarfaccept". Also, skip to the comma.
|
||||
// like "ackbarfdelete". Also, skip to the comma.
|
||||
boolean seencomma = false;
|
||||
while (i >= matchlen && !seencomma) {
|
||||
switch(a[i-matchlen]) {
|
||||
case ',':
|
||||
seencomma = true;
|
||||
break;
|
||||
switch (c = a[i-matchlen]) {
|
||||
case ' ': case '\r': case '\n':
|
||||
case '\f': case '\t':
|
||||
break;
|
||||
default:
|
||||
if (c == ',' && i > matchlen) {
|
||||
seencomma = true;
|
||||
break;
|
||||
}
|
||||
throw new IllegalArgumentException(
|
||||
"invalid permission: " + actions);
|
||||
}
|
||||
@ -1127,10 +1142,10 @@ final class FilePermissionCollection extends PermissionCollection
|
||||
*
|
||||
* @param permission the Permission object to add.
|
||||
*
|
||||
* @throws IllegalArgumentException - if the permission is not a
|
||||
* @throws IllegalArgumentException if the permission is not a
|
||||
* FilePermission
|
||||
*
|
||||
* @throws SecurityException - if this FilePermissionCollection object
|
||||
* @throws SecurityException if this FilePermissionCollection object
|
||||
* has been marked readonly
|
||||
*/
|
||||
@Override
|
||||
|
@ -70,4 +70,35 @@ class NullPointerException extends RuntimeException {
|
||||
public NullPointerException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the detail message string of this throwable.
|
||||
*
|
||||
* <p> If a non-null message was supplied in a constructor it is
|
||||
* returned. Otherwise, an implementation specific message or
|
||||
* {@code null} is returned.
|
||||
*
|
||||
* @implNote
|
||||
* If no explicit message was passed to the constructor, and as
|
||||
* long as certain internal information is available, a verbose
|
||||
* description of the null reference is returned.
|
||||
* The internal information is not available in deserialized
|
||||
* NullPointerExceptions.
|
||||
*
|
||||
* @return the detail message string, which may be {@code null}.
|
||||
*/
|
||||
public String getMessage() {
|
||||
String message = super.getMessage();
|
||||
if (message == null) {
|
||||
return getExtendedNPEMessage();
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an extended exception message. This returns a string describing
|
||||
* the location and cause of the exception. It returns null for
|
||||
* exceptions where this is not applicable.
|
||||
*/
|
||||
private native String getExtendedNPEMessage();
|
||||
}
|
||||
|
@ -145,6 +145,15 @@ import java.util.StringTokenizer;
|
||||
* </tr>
|
||||
*
|
||||
* <tr>
|
||||
* <th scope="row">setSocketImpl</th>
|
||||
* <td>The ability to create a sub-class of Socket or ServerSocket with a
|
||||
* user specified SocketImpl.</td>
|
||||
* <td>Malicious user-defined SocketImpls can change the behavior of
|
||||
* Socket and ServerSocket in surprising ways, by virtue of their
|
||||
* ability to access the protected fields of SocketImpl.</td>
|
||||
* </tr>
|
||||
*
|
||||
* <tr>
|
||||
* <th scope="row">specifyStreamHandler</th>
|
||||
* <td>The ability
|
||||
* to specify a stream handler when constructing a URL</td>
|
||||
|
@ -32,6 +32,7 @@ import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.Collections;
|
||||
|
||||
import sun.security.util.SecurityConstants;
|
||||
import sun.net.PlatformSocketImpl;
|
||||
|
||||
/**
|
||||
@ -73,13 +74,25 @@ class ServerSocket implements java.io.Closeable {
|
||||
*
|
||||
* @throws NullPointerException if impl is {@code null}.
|
||||
*
|
||||
* @throws SecurityException if a security manager is set and
|
||||
* its {@code checkPermission} method doesn't allow
|
||||
* {@code NetPermission("setSocketImpl")}.
|
||||
* @since 12
|
||||
*/
|
||||
protected ServerSocket(SocketImpl impl) {
|
||||
Objects.requireNonNull(impl);
|
||||
checkPermission();
|
||||
this.impl = impl;
|
||||
}
|
||||
|
||||
private static Void checkPermission() {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(SecurityConstants.SET_SOCKETIMPL_PERMISSION);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an unbound server socket.
|
||||
*
|
||||
|
@ -25,6 +25,8 @@
|
||||
|
||||
package java.net;
|
||||
|
||||
import sun.security.util.SecurityConstants;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
@ -182,12 +184,28 @@ class Socket implements java.io.Closeable {
|
||||
*
|
||||
* @throws SocketException if there is an error in the underlying protocol,
|
||||
* such as a TCP error.
|
||||
*
|
||||
* @throws SecurityException if {@code impl} is non-null and a security manager is set
|
||||
* and its {@code checkPermission} method doesn't allow {@code NetPermission("setSocketImpl")}.
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
protected Socket(SocketImpl impl) throws SocketException {
|
||||
checkPermission(impl);
|
||||
this.impl = impl;
|
||||
}
|
||||
|
||||
private static Void checkPermission(SocketImpl impl) {
|
||||
if (impl == null) {
|
||||
return null;
|
||||
}
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(SecurityConstants.SET_SOCKETIMPL_PERMISSION);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a stream socket and connects it to the specified port
|
||||
* number on the named host.
|
||||
|
@ -287,6 +287,11 @@ public final class SocketPermission extends Permission
|
||||
* @param host the hostname or IP address of the computer, optionally
|
||||
* including a colon followed by a port or port range.
|
||||
* @param action the action string.
|
||||
*
|
||||
* @throws NullPointerException if any parameters are null
|
||||
* @throws IllegalArgumentException if the format of {@code host} is
|
||||
* invalid, or if the {@code action} string is empty, malformed, or
|
||||
* contains an action other than the specified possible actions
|
||||
*/
|
||||
public SocketPermission(String host, String action) {
|
||||
super(getHost(host));
|
||||
@ -589,14 +594,15 @@ public final class SocketPermission extends Permission
|
||||
// like "ackbarfaccept". Also, skip to the comma.
|
||||
boolean seencomma = false;
|
||||
while (i >= matchlen && !seencomma) {
|
||||
switch(a[i-matchlen]) {
|
||||
case ',':
|
||||
seencomma = true;
|
||||
break;
|
||||
switch (c = a[i-matchlen]) {
|
||||
case ' ': case '\r': case '\n':
|
||||
case '\f': case '\t':
|
||||
break;
|
||||
default:
|
||||
if (c == ',' && i > matchlen) {
|
||||
seencomma = true;
|
||||
break;
|
||||
}
|
||||
throw new IllegalArgumentException(
|
||||
"invalid permission: " + action);
|
||||
}
|
||||
@ -1361,10 +1367,10 @@ final class SocketPermissionCollection extends PermissionCollection
|
||||
*
|
||||
* @param permission the Permission object to add.
|
||||
*
|
||||
* @throws IllegalArgumentException - if the permission is not a
|
||||
* @throws IllegalArgumentException if the permission is not a
|
||||
* SocketPermission
|
||||
*
|
||||
* @throws SecurityException - if this SocketPermissionCollection object
|
||||
* @throws SecurityException if this SocketPermissionCollection object
|
||||
* has been marked readonly
|
||||
*/
|
||||
@Override
|
||||
|
@ -484,6 +484,16 @@ public final class URL implements java.io.Serializable {
|
||||
throw new MalformedURLException(s);
|
||||
}
|
||||
}
|
||||
if ("jar".equalsIgnoreCase(protocol)) {
|
||||
if (handler instanceof sun.net.www.protocol.jar.Handler) {
|
||||
// URL.openConnection() would throw a confusing exception
|
||||
// so generate a better exception here instead.
|
||||
String s = ((sun.net.www.protocol.jar.Handler) handler).checkNestedProtocol(file);
|
||||
if (s != null) {
|
||||
throw new MalformedURLException(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -178,10 +178,10 @@ final class AllPermissionCollection
|
||||
*
|
||||
* @param permission the Permission object to add.
|
||||
*
|
||||
* @throws IllegalArgumentException - if the permission is not a
|
||||
* @throws IllegalArgumentException if the permission is not an
|
||||
* AllPermission
|
||||
*
|
||||
* @throws SecurityException - if this AllPermissionCollection object
|
||||
* @throws SecurityException if this AllPermissionCollection object
|
||||
* has been marked readonly
|
||||
*/
|
||||
|
||||
|
@ -349,13 +349,13 @@ final class BasicPermissionCollection
|
||||
*
|
||||
* @param permission the Permission object to add.
|
||||
*
|
||||
* @throws IllegalArgumentException - if the permission is not a
|
||||
* @throws IllegalArgumentException if the permission is not a
|
||||
* BasicPermission, or if
|
||||
* the permission is not of the
|
||||
* same Class as the other
|
||||
* permissions in this collection.
|
||||
*
|
||||
* @throws SecurityException - if this BasicPermissionCollection object
|
||||
* @throws SecurityException if this BasicPermissionCollection object
|
||||
* has been marked readonly
|
||||
*/
|
||||
@Override
|
||||
|
@ -107,9 +107,9 @@ public abstract class PermissionCollection implements java.io.Serializable {
|
||||
*
|
||||
* @param permission the Permission object to add.
|
||||
*
|
||||
* @throws SecurityException - if this PermissionCollection object
|
||||
* @throws SecurityException if this PermissionCollection object
|
||||
* has been marked readonly
|
||||
* @throws IllegalArgumentException - if this PermissionCollection
|
||||
* @throws IllegalArgumentException if this PermissionCollection
|
||||
* object is a homogeneous collection and the permission
|
||||
* is not of the correct type.
|
||||
*/
|
||||
|
@ -837,7 +837,7 @@ public abstract class Policy {
|
||||
*
|
||||
* @param permission the Permission object to add.
|
||||
*
|
||||
* @throws SecurityException - if this PermissionCollection object
|
||||
* @throws SecurityException if this PermissionCollection object
|
||||
* has been marked readonly
|
||||
*/
|
||||
@Override public void add(Permission permission) {
|
||||
|
@ -2756,7 +2756,10 @@ public class DecimalFormat extends NumberFormat {
|
||||
/**
|
||||
* Return the grouping size. Grouping size is the number of digits between
|
||||
* grouping separators in the integer portion of a number. For example,
|
||||
* in the number "123,456.78", the grouping size is 3.
|
||||
* in the number "123,456.78", the grouping size is 3. Grouping size of
|
||||
* zero designates that grouping is not used, which provides the same
|
||||
* formatting as if calling {@link #setGroupingUsed(boolean)
|
||||
* setGroupingUsed(false)}.
|
||||
*
|
||||
* @return the grouping size
|
||||
* @see #setGroupingSize
|
||||
@ -2770,16 +2773,28 @@ public class DecimalFormat extends NumberFormat {
|
||||
/**
|
||||
* Set the grouping size. Grouping size is the number of digits between
|
||||
* grouping separators in the integer portion of a number. For example,
|
||||
* in the number "123,456.78", the grouping size is 3.
|
||||
* <br>
|
||||
* in the number "123,456.78", the grouping size is 3. Grouping size of
|
||||
* zero designates that grouping is not used, which provides the same
|
||||
* formatting as if calling {@link #setGroupingUsed(boolean)
|
||||
* setGroupingUsed(false)}.
|
||||
* <p>
|
||||
* The value passed in is converted to a byte, which may lose information.
|
||||
* Values that are negative or greater than
|
||||
* {@link java.lang.Byte#MAX_VALUE Byte.MAX_VALUE}, will throw an
|
||||
* {@code IllegalArgumentException}.
|
||||
*
|
||||
* @param newValue the new grouping size
|
||||
* @see #getGroupingSize
|
||||
* @see java.text.NumberFormat#setGroupingUsed
|
||||
* @see java.text.DecimalFormatSymbols#setGroupingSeparator
|
||||
* @throws IllegalArgumentException if {@code newValue} is negative or
|
||||
* greater than {@link java.lang.Byte#MAX_VALUE Byte.MAX_VALUE}
|
||||
*/
|
||||
public void setGroupingSize (int newValue) {
|
||||
if (newValue < 0 || newValue > Byte.MAX_VALUE) {
|
||||
throw new IllegalArgumentException(
|
||||
"newValue is out of valid range. value: " + newValue);
|
||||
}
|
||||
groupingSize = (byte)newValue;
|
||||
fastPathCheckNeeded = true;
|
||||
}
|
||||
@ -3906,6 +3921,12 @@ public class DecimalFormat extends NumberFormat {
|
||||
// Didn't have exponential fields
|
||||
useExponentialNotation = false;
|
||||
}
|
||||
|
||||
// Restore the invariant value if groupingSize is invalid.
|
||||
if (groupingSize < 0) {
|
||||
groupingSize = 3;
|
||||
}
|
||||
|
||||
serialVersionOnStream = currentSerialVersion;
|
||||
}
|
||||
|
||||
@ -4009,14 +4030,15 @@ public class DecimalFormat extends NumberFormat {
|
||||
|
||||
/**
|
||||
* The number of digits between grouping separators in the integer
|
||||
* portion of a number. Must be greater than 0 if
|
||||
* portion of a number. Must be non-negative and less than or equal to
|
||||
* {@link java.lang.Byte#MAX_VALUE Byte.MAX_VALUE} if
|
||||
* {@code NumberFormat.groupingUsed} is true.
|
||||
*
|
||||
* @serial
|
||||
* @see #getGroupingSize
|
||||
* @see java.text.NumberFormat#isGroupingUsed
|
||||
*/
|
||||
private byte groupingSize = 3; // invariant, > 0 if useThousands
|
||||
private byte groupingSize = 3; // invariant, 0 - 127, if groupingUsed
|
||||
|
||||
/**
|
||||
* If true, forces the decimal separator to always appear in a formatted
|
||||
|
@ -463,10 +463,10 @@ final class PropertyPermissionCollection extends PermissionCollection
|
||||
*
|
||||
* @param permission the Permission object to add.
|
||||
*
|
||||
* @throws IllegalArgumentException - if the permission is not a
|
||||
* @throws IllegalArgumentException if the permission is not a
|
||||
* PropertyPermission
|
||||
*
|
||||
* @throws SecurityException - if this PropertyPermissionCollection
|
||||
* @throws SecurityException if this PropertyPermissionCollection
|
||||
* object has been marked readonly
|
||||
*/
|
||||
@Override
|
||||
|
@ -100,6 +100,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
|
||||
private static final long serialVersionUID = -817911632652898426L;
|
||||
|
||||
/** The queued items */
|
||||
@SuppressWarnings("serial") // Conditionally serializable
|
||||
final Object[] items;
|
||||
|
||||
/** items index for next take, poll, peek or remove */
|
||||
@ -120,9 +121,11 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
|
||||
final ReentrantLock lock;
|
||||
|
||||
/** Condition for waiting takes */
|
||||
@SuppressWarnings("serial") // Classes implementing Condition may be serializable.
|
||||
private final Condition notEmpty;
|
||||
|
||||
/** Condition for waiting puts */
|
||||
@SuppressWarnings("serial") // Classes implementing Condition may be serializable.
|
||||
private final Condition notFull;
|
||||
|
||||
/**
|
||||
|
@ -4584,6 +4584,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
||||
public static class KeySetView<K,V> extends CollectionView<K,V,K>
|
||||
implements Set<K>, java.io.Serializable {
|
||||
private static final long serialVersionUID = 7249069246763182397L;
|
||||
@SuppressWarnings("serial") // Conditionally serializable
|
||||
private final V value;
|
||||
KeySetView(ConcurrentHashMap<K,V> map, V value) { // non-public
|
||||
super(map);
|
||||
|
@ -334,6 +334,7 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
|
||||
* nested classes.)
|
||||
* @serial
|
||||
*/
|
||||
@SuppressWarnings("serial") // Conditionally serializable
|
||||
final Comparator<? super K> comparator;
|
||||
|
||||
/** Lazily initialized topmost index of the skiplist. */
|
||||
@ -2375,8 +2376,10 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
|
||||
/** Underlying map */
|
||||
final ConcurrentSkipListMap<K,V> m;
|
||||
/** lower bound key, or null if from start */
|
||||
@SuppressWarnings("serial") // Conditionally serializable
|
||||
private final K lo;
|
||||
/** upper bound key, or null if to end */
|
||||
@SuppressWarnings("serial") // Conditionally serializable
|
||||
private final K hi;
|
||||
/** inclusion flag for lo */
|
||||
private final boolean loInclusive;
|
||||
|
@ -103,6 +103,7 @@ public class ConcurrentSkipListSet<E>
|
||||
* element. This field is declared final for the sake of thread
|
||||
* safety, which entails some ugliness in clone().
|
||||
*/
|
||||
@SuppressWarnings("serial") // Conditionally serializable
|
||||
private final ConcurrentNavigableMap<E,Object> m;
|
||||
|
||||
/**
|
||||
|
@ -1374,7 +1374,9 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
|
||||
*/
|
||||
static final class AdaptedRunnable<T> extends ForkJoinTask<T>
|
||||
implements RunnableFuture<T> {
|
||||
@SuppressWarnings("serial") // Conditionally serializable
|
||||
final Runnable runnable;
|
||||
@SuppressWarnings("serial") // Conditionally serializable
|
||||
T result;
|
||||
AdaptedRunnable(Runnable runnable, T result) {
|
||||
if (runnable == null) throw new NullPointerException();
|
||||
@ -1396,6 +1398,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
|
||||
*/
|
||||
static final class AdaptedRunnableAction extends ForkJoinTask<Void>
|
||||
implements RunnableFuture<Void> {
|
||||
@SuppressWarnings("serial") // Conditionally serializable
|
||||
final Runnable runnable;
|
||||
AdaptedRunnableAction(Runnable runnable) {
|
||||
if (runnable == null) throw new NullPointerException();
|
||||
@ -1415,6 +1418,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
|
||||
* Adapter for Runnables in which failure forces worker exception.
|
||||
*/
|
||||
static final class RunnableExecuteAction extends ForkJoinTask<Void> {
|
||||
@SuppressWarnings("serial") // Conditionally serializable
|
||||
final Runnable runnable;
|
||||
RunnableExecuteAction(Runnable runnable) {
|
||||
if (runnable == null) throw new NullPointerException();
|
||||
@ -1434,7 +1438,9 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
|
||||
*/
|
||||
static final class AdaptedCallable<T> extends ForkJoinTask<T>
|
||||
implements RunnableFuture<T> {
|
||||
@SuppressWarnings("serial") // Conditionally serializable
|
||||
final Callable<? extends T> callable;
|
||||
@SuppressWarnings("serial") // Conditionally serializable
|
||||
T result;
|
||||
AdaptedCallable(Callable<? extends T> callable) {
|
||||
if (callable == null) throw new NullPointerException();
|
||||
|
@ -159,9 +159,11 @@ public class LinkedBlockingDeque<E>
|
||||
final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
/** Condition for waiting takes */
|
||||
@SuppressWarnings("serial") // Classes implementing Condition may be serializable.
|
||||
private final Condition notEmpty = lock.newCondition();
|
||||
|
||||
/** Condition for waiting puts */
|
||||
@SuppressWarnings("serial") // Classes implementing Condition may be serializable.
|
||||
private final Condition notFull = lock.newCondition();
|
||||
|
||||
/**
|
||||
|
@ -156,12 +156,14 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
|
||||
private final ReentrantLock takeLock = new ReentrantLock();
|
||||
|
||||
/** Wait queue for waiting takes */
|
||||
@SuppressWarnings("serial") // Classes implementing Condition may be serializable.
|
||||
private final Condition notEmpty = takeLock.newCondition();
|
||||
|
||||
/** Lock held by put, offer, etc */
|
||||
private final ReentrantLock putLock = new ReentrantLock();
|
||||
|
||||
/** Wait queue for waiting puts */
|
||||
@SuppressWarnings("serial") // Classes implementing Condition may be serializable.
|
||||
private final Condition notFull = putLock.newCondition();
|
||||
|
||||
/**
|
||||
|
@ -173,6 +173,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
|
||||
/**
|
||||
* Condition for blocking when empty.
|
||||
*/
|
||||
@SuppressWarnings("serial") // Classes implementing Condition may be serializable.
|
||||
private final Condition notEmpty = lock.newCondition();
|
||||
|
||||
/**
|
||||
|
@ -71,6 +71,7 @@ public abstract class RecursiveTask<V> extends ForkJoinTask<V> {
|
||||
/**
|
||||
* The result of the computation.
|
||||
*/
|
||||
@SuppressWarnings("serial") // Conditionally serializable
|
||||
V result;
|
||||
|
||||
/**
|
||||
|
@ -604,8 +604,10 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
|
||||
private static final long serialVersionUID = 6138294804551838833L;
|
||||
|
||||
/** Thread this worker is running in. Null if factory fails. */
|
||||
@SuppressWarnings("serial") // Unlikely to be serializable
|
||||
final Thread thread;
|
||||
/** Initial task to run. Possibly null. */
|
||||
@SuppressWarnings("serial") // Not statically typed as Serializable
|
||||
Runnable firstTask;
|
||||
/** Per-thread task counter */
|
||||
volatile long completedTasks;
|
||||
|
@ -60,6 +60,7 @@ public class AtomicReference<V> implements java.io.Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial") // Conditionally serializable
|
||||
private volatile V value;
|
||||
|
||||
/**
|
||||
|
@ -55,6 +55,7 @@ public class AtomicReferenceArray<E> implements java.io.Serializable {
|
||||
private static final long serialVersionUID = -6209656149925076980L;
|
||||
private static final VarHandle AA
|
||||
= MethodHandles.arrayElementVarHandle(Object[].class);
|
||||
@SuppressWarnings("serial") // Conditionally serializable
|
||||
private final Object[] array; // must have exact type Object[]
|
||||
|
||||
/**
|
||||
|
@ -84,6 +84,7 @@ import java.util.function.DoubleBinaryOperator;
|
||||
public class DoubleAccumulator extends Striped64 implements Serializable {
|
||||
private static final long serialVersionUID = 7249069246863182397L;
|
||||
|
||||
@SuppressWarnings("serial") // Not statically typed as Serializable
|
||||
private final DoubleBinaryOperator function;
|
||||
private final long identity; // use long representation
|
||||
|
||||
@ -245,6 +246,7 @@ public class DoubleAccumulator extends Striped64 implements Serializable {
|
||||
* The function used for updates.
|
||||
* @serial
|
||||
*/
|
||||
@SuppressWarnings("serial") // Not statically typed as Serializable
|
||||
private final DoubleBinaryOperator function;
|
||||
|
||||
/**
|
||||
|
@ -82,6 +82,7 @@ import java.util.function.LongBinaryOperator;
|
||||
public class LongAccumulator extends Striped64 implements Serializable {
|
||||
private static final long serialVersionUID = 7249069246863182397L;
|
||||
|
||||
@SuppressWarnings("serial") // Not statically typed as Serializable
|
||||
private final LongBinaryOperator function;
|
||||
private final long identity;
|
||||
|
||||
@ -239,6 +240,7 @@ public class LongAccumulator extends Striped64 implements Serializable {
|
||||
* The function used for updates.
|
||||
* @serial
|
||||
*/
|
||||
@SuppressWarnings("serial") // Not statically typed as Serializable
|
||||
private final LongBinaryOperator function;
|
||||
|
||||
/**
|
||||
|
@ -1427,7 +1427,11 @@ public final class Pattern
|
||||
localTCNCount = 0;
|
||||
|
||||
if (!pattern.isEmpty()) {
|
||||
compile();
|
||||
try {
|
||||
compile();
|
||||
} catch (StackOverflowError soe) {
|
||||
throw error("Stack overflow during pattern compilation");
|
||||
}
|
||||
} else {
|
||||
root = new Start(lastAccept);
|
||||
matchRoot = lastAccept;
|
||||
@ -1965,6 +1969,10 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
|
||||
int ch = temp[cursor++];
|
||||
while (ch != 0 && !isLineSeparator(ch))
|
||||
ch = temp[cursor++];
|
||||
if (ch == 0 && cursor > patternLength) {
|
||||
cursor = patternLength;
|
||||
ch = temp[cursor++];
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
@ -1975,6 +1983,10 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
|
||||
int ch = temp[++cursor];
|
||||
while (ch != 0 && !isLineSeparator(ch))
|
||||
ch = temp[++cursor];
|
||||
if (ch == 0 && cursor > patternLength) {
|
||||
cursor = patternLength;
|
||||
ch = temp[cursor];
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
@ -3415,9 +3427,10 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
|
||||
private int N() {
|
||||
if (read() == '{') {
|
||||
int i = cursor;
|
||||
while (cursor < patternLength && read() != '}') {}
|
||||
if (cursor > patternLength)
|
||||
throw error("Unclosed character name escape sequence");
|
||||
while (read() != '}') {
|
||||
if (cursor >= patternLength)
|
||||
throw error("Unclosed character name escape sequence");
|
||||
}
|
||||
String name = new String(temp, i, cursor - i - 1);
|
||||
try {
|
||||
return Character.codePointOf(name);
|
||||
|
@ -2171,6 +2171,10 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||
} while (retryTunnel < maxRedirects);
|
||||
|
||||
if (retryTunnel >= maxRedirects || (respCode != HTTP_OK)) {
|
||||
if (respCode != HTTP_PROXY_AUTH) {
|
||||
// remove all but authenticate responses
|
||||
responses.reset();
|
||||
}
|
||||
throw new IOException("Unable to tunnel through proxy."+
|
||||
" Proxy returns \"" +
|
||||
statusLine + "\"");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -121,6 +121,13 @@ public class Handler extends java.net.URLStreamHandler {
|
||||
return h;
|
||||
}
|
||||
|
||||
public String checkNestedProtocol(String spec) {
|
||||
if (spec.regionMatches(true, 0, "jar:", 0, 4)) {
|
||||
return "Nested JAR URLs are not supported";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
@ -146,6 +153,12 @@ public class Handler extends java.net.URLStreamHandler {
|
||||
: false;
|
||||
spec = spec.substring(start, limit);
|
||||
|
||||
String exceptionMessage = checkNestedProtocol(spec);
|
||||
if (exceptionMessage != null) {
|
||||
// NPE will be transformed into MalformedURLException by the caller
|
||||
throw new NullPointerException(exceptionMessage);
|
||||
}
|
||||
|
||||
if (absoluteSpec) {
|
||||
file = parseAbsoluteSpec(spec);
|
||||
} else if (!refOnly) {
|
||||
|
@ -37,6 +37,9 @@ import java.net.StandardSocketOptions;
|
||||
import java.nio.channels.IllegalBlockingModeException;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
@ -59,7 +62,12 @@ class ServerSocketAdaptor // package-private
|
||||
private volatile int timeout;
|
||||
|
||||
static ServerSocket create(ServerSocketChannelImpl ssc) {
|
||||
return new ServerSocketAdaptor(ssc);
|
||||
PrivilegedExceptionAction<ServerSocket> pa = () -> new ServerSocketAdaptor(ssc);
|
||||
try {
|
||||
return AccessController.doPrivileged(pa);
|
||||
} catch (PrivilegedActionException pae) {
|
||||
throw new InternalError("Should not reach here", pae);
|
||||
}
|
||||
}
|
||||
|
||||
private ServerSocketAdaptor(ServerSocketChannelImpl ssc) {
|
||||
|
@ -36,6 +36,9 @@ import java.net.SocketException;
|
||||
import java.net.SocketOption;
|
||||
import java.net.StandardSocketOptions;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
@ -61,10 +64,11 @@ class SocketAdaptor
|
||||
}
|
||||
|
||||
static Socket create(SocketChannelImpl sc) {
|
||||
PrivilegedExceptionAction<Socket> pa = () -> new SocketAdaptor(sc);
|
||||
try {
|
||||
return new SocketAdaptor(sc);
|
||||
} catch (SocketException e) {
|
||||
throw new InternalError("Should not reach here");
|
||||
return AccessController.doPrivileged(pa);
|
||||
} catch (PrivilegedActionException pae) {
|
||||
throw new InternalError("Should not reach here", pae);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,7 @@ final class SupportedGroupsExtension {
|
||||
// Primary XDH (RFC 7748) curves
|
||||
NamedGroup.X25519,
|
||||
|
||||
// Primary NIST curves (e.g. used in TLSv1.3)
|
||||
// Primary NIST Suite B curves
|
||||
NamedGroup.SECP256_R1,
|
||||
NamedGroup.SECP384_R1,
|
||||
NamedGroup.SECP521_R1,
|
||||
@ -209,17 +209,6 @@ final class SupportedGroupsExtension {
|
||||
// Secondary XDH curves
|
||||
NamedGroup.X448,
|
||||
|
||||
// Secondary NIST curves
|
||||
NamedGroup.SECT283_K1,
|
||||
NamedGroup.SECT283_R1,
|
||||
NamedGroup.SECT409_K1,
|
||||
NamedGroup.SECT409_R1,
|
||||
NamedGroup.SECT571_K1,
|
||||
NamedGroup.SECT571_R1,
|
||||
|
||||
// non-NIST curves
|
||||
NamedGroup.SECP256_K1,
|
||||
|
||||
// FFDHE (RFC 7919)
|
||||
NamedGroup.FFDHE_2048,
|
||||
NamedGroup.FFDHE_3072,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -42,8 +42,11 @@ public class FilePermCompat {
|
||||
public static final boolean compat;
|
||||
|
||||
static {
|
||||
String flag = GetPropertyAction.privilegedGetProperty(
|
||||
"jdk.io.permissionsUseCanonicalPath", "false");
|
||||
String flag = SecurityProperties.privilegedGetOverridable(
|
||||
"jdk.io.permissionsUseCanonicalPath");
|
||||
if (flag == null) {
|
||||
flag = "false";
|
||||
}
|
||||
switch (flag) {
|
||||
case "true":
|
||||
nb = false;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -97,6 +97,10 @@ public final class SecurityConstants {
|
||||
public static final NetPermission GET_RESPONSECACHE_PERMISSION =
|
||||
new NetPermission("getResponseCache");
|
||||
|
||||
// java.net.ServerSocket, java.net.Socket
|
||||
public static final NetPermission SET_SOCKETIMPL_PERMISSION =
|
||||
new NetPermission("setSocketImpl");
|
||||
|
||||
// java.lang.SecurityManager, sun.applet.AppletPanel
|
||||
public static final RuntimePermission CREATE_CLASSLOADER_PERMISSION =
|
||||
new RuntimePermission("createClassLoader");
|
||||
|
@ -1213,3 +1213,51 @@ jdk.sasl.disabledMechanisms=
|
||||
# if this property is not enabled.
|
||||
#
|
||||
jdk.security.caDistrustPolicies=SYMANTEC_TLS
|
||||
|
||||
#
|
||||
# FilePermission path canonicalization
|
||||
#
|
||||
# This security property dictates how the path argument is processed and stored
|
||||
# while constructing a FilePermission object. If the value is set to true, the
|
||||
# path argument is canonicalized and FilePermission methods (such as implies,
|
||||
# equals, and hashCode) are implemented based on this canonicalized result.
|
||||
# Otherwise, the path argument is not canonicalized and FilePermission methods are
|
||||
# implemented based on the original input. See the implementation note of the
|
||||
# FilePermission class for more details.
|
||||
#
|
||||
# If a system property of the same name is also specified, it supersedes the
|
||||
# security property value defined here.
|
||||
#
|
||||
# The default value for this property is false.
|
||||
#
|
||||
jdk.io.permissionsUseCanonicalPath=false
|
||||
|
||||
|
||||
#
|
||||
# Policies for the proxy_impersonator Kerberos ccache configuration entry
|
||||
#
|
||||
# The proxy_impersonator ccache configuration entry indicates that the ccache
|
||||
# is a synthetic delegated credential for use with S4U2Proxy by an intermediate
|
||||
# server. The ccache file should also contain the TGT of this server and
|
||||
# an evidence ticket from the default principal of the ccache to this server.
|
||||
#
|
||||
# This security property determines how Java uses this configuration entry.
|
||||
# There are 3 possible values:
|
||||
#
|
||||
# no-impersonate - Ignore this configuration entry, and always act as
|
||||
# the owner of the TGT (if it exists).
|
||||
#
|
||||
# try-impersonate - Try impersonation when this configuration entry exists.
|
||||
# If no matching TGT or evidence ticket is found,
|
||||
# fallback to no-impersonate.
|
||||
#
|
||||
# always-impersonate - Always impersonate when this configuration entry exists.
|
||||
# If no matching TGT or evidence ticket is found,
|
||||
# no initial credential is read from the ccache.
|
||||
#
|
||||
# The default value is "always-impersonate".
|
||||
#
|
||||
# If a system property of the same name is also specified, it supersedes the
|
||||
# security property value defined here.
|
||||
#
|
||||
#jdk.security.krb5.default.initiate.credential=always-impersonate
|
||||
|
36
src/java.base/share/native/libjava/NullPointerException.c
Normal file
36
src/java.base/share/native/libjava/NullPointerException.c
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "jni.h"
|
||||
#include "jvm.h"
|
||||
|
||||
#include "java_lang_NullPointerException.h"
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_java_lang_NullPointerException_getExtendedNPEMessage(JNIEnv *env, jobject throwable)
|
||||
{
|
||||
return JVM_GetExtendedNPEMessage(env, throwable);
|
||||
}
|
@ -38,6 +38,7 @@ import java.lang.ProcessBuilder.Redirect;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
@ -46,6 +47,8 @@ import java.util.regex.Pattern;
|
||||
import jdk.internal.access.JavaIOFileDescriptorAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.ref.CleanerFactory;
|
||||
import sun.security.action.GetBooleanAction;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/* This class is for the exclusive use of ProcessBuilder.start() to
|
||||
* create new processes.
|
||||
@ -209,12 +212,15 @@ final class ProcessImpl extends Process {
|
||||
|
||||
private static final int VERIFICATION_CMD_BAT = 0;
|
||||
private static final int VERIFICATION_WIN32 = 1;
|
||||
private static final int VERIFICATION_LEGACY = 2;
|
||||
private static final int VERIFICATION_WIN32_SAFE = 2; // inside quotes not allowed
|
||||
private static final int VERIFICATION_LEGACY = 3;
|
||||
// See Command shell overview for documentation of special characters.
|
||||
// https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-xp/bb490954(v=technet.10)
|
||||
private static final char ESCAPE_VERIFICATION[][] = {
|
||||
// We guarantee the only command file execution for implicit [cmd.exe] run.
|
||||
// http://technet.microsoft.com/en-us/library/bb490954.aspx
|
||||
{' ', '\t', '<', '>', '&', '|', '^'},
|
||||
|
||||
{' ', '\t', '<', '>'},
|
||||
{' ', '\t', '<', '>'},
|
||||
{' ', '\t'}
|
||||
};
|
||||
@ -231,8 +237,25 @@ final class ProcessImpl extends Process {
|
||||
cmdbuf.append(' ');
|
||||
String s = cmd[i];
|
||||
if (needsEscaping(verificationType, s)) {
|
||||
cmdbuf.append('"').append(s);
|
||||
cmdbuf.append('"');
|
||||
|
||||
if (verificationType == VERIFICATION_WIN32_SAFE) {
|
||||
// Insert the argument, adding '\' to quote any interior quotes
|
||||
int length = s.length();
|
||||
for (int j = 0; j < length; j++) {
|
||||
char c = s.charAt(j);
|
||||
if (c == DOUBLEQUOTE) {
|
||||
int count = countLeadingBackslash(verificationType, s, j);
|
||||
while (count-- > 0) {
|
||||
cmdbuf.append(BACKSLASH); // double the number of backslashes
|
||||
}
|
||||
cmdbuf.append(BACKSLASH); // backslash to quote the quote
|
||||
}
|
||||
cmdbuf.append(c);
|
||||
}
|
||||
} else {
|
||||
cmdbuf.append(s);
|
||||
}
|
||||
// The code protects the [java.exe] and console command line
|
||||
// parser, that interprets the [\"] combination as an escape
|
||||
// sequence for the ["] char.
|
||||
@ -245,8 +268,9 @@ final class ProcessImpl extends Process {
|
||||
// command line parser. The case of the [""] tail escape
|
||||
// sequence could not be realized due to the argument validation
|
||||
// procedure.
|
||||
if ((verificationType != VERIFICATION_CMD_BAT) && s.endsWith("\\")) {
|
||||
cmdbuf.append('\\');
|
||||
int count = countLeadingBackslash(verificationType, s, s.length());
|
||||
while (count-- > 0) {
|
||||
cmdbuf.append(BACKSLASH); // double the number of backslashes
|
||||
}
|
||||
cmdbuf.append('"');
|
||||
} else {
|
||||
@ -256,26 +280,16 @@ final class ProcessImpl extends Process {
|
||||
return cmdbuf.toString();
|
||||
}
|
||||
|
||||
private static boolean isQuoted(boolean noQuotesInside, String arg,
|
||||
String errorMessage) {
|
||||
int lastPos = arg.length() - 1;
|
||||
if (lastPos >=1 && arg.charAt(0) == '"' && arg.charAt(lastPos) == '"') {
|
||||
// The argument has already been quoted.
|
||||
if (noQuotesInside) {
|
||||
if (arg.indexOf('"', 1) != lastPos) {
|
||||
// There is ["] inside.
|
||||
throw new IllegalArgumentException(errorMessage);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (noQuotesInside) {
|
||||
if (arg.indexOf('"') >= 0) {
|
||||
// There is ["] inside.
|
||||
throw new IllegalArgumentException(errorMessage);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
/**
|
||||
* Return the argument without quotes (1st and last) if present, else the arg.
|
||||
* @param str a string
|
||||
* @return the string without 1st and last quotes
|
||||
*/
|
||||
private static String unQuote(String str) {
|
||||
int len = str.length();
|
||||
return (len >= 2 && str.charAt(0) == DOUBLEQUOTE && str.charAt(len - 1) == DOUBLEQUOTE)
|
||||
? str.substring(1, len - 1)
|
||||
: str;
|
||||
}
|
||||
|
||||
private static boolean needsEscaping(int verificationType, String arg) {
|
||||
@ -286,9 +300,26 @@ final class ProcessImpl extends Process {
|
||||
|
||||
// For [.exe] or [.com] file the unpaired/internal ["]
|
||||
// in the argument is not a problem.
|
||||
boolean argIsQuoted = isQuoted(
|
||||
(verificationType == VERIFICATION_CMD_BAT),
|
||||
arg, "Argument has embedded quote, use the explicit CMD.EXE call.");
|
||||
String unquotedArg = unQuote(arg);
|
||||
boolean argIsQuoted = !arg.equals(unquotedArg);
|
||||
boolean embeddedQuote = unquotedArg.indexOf(DOUBLEQUOTE) >= 0;
|
||||
|
||||
switch (verificationType) {
|
||||
case VERIFICATION_CMD_BAT:
|
||||
if (embeddedQuote) {
|
||||
throw new IllegalArgumentException("Argument has embedded quote, " +
|
||||
"use the explicit CMD.EXE call.");
|
||||
}
|
||||
break; // break determine whether to quote
|
||||
case VERIFICATION_WIN32_SAFE:
|
||||
if (argIsQuoted && embeddedQuote) {
|
||||
throw new IllegalArgumentException("Malformed argument has embedded quote: "
|
||||
+ unquotedArg);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!argIsQuoted) {
|
||||
char testEscape[] = ESCAPE_VERIFICATION[verificationType];
|
||||
@ -304,13 +335,13 @@ final class ProcessImpl extends Process {
|
||||
private static String getExecutablePath(String path)
|
||||
throws IOException
|
||||
{
|
||||
boolean pathIsQuoted = isQuoted(true, path,
|
||||
"Executable name has embedded quote, split the arguments");
|
||||
|
||||
String name = unQuote(path);
|
||||
if (name.indexOf(DOUBLEQUOTE) >= 0) {
|
||||
throw new IllegalArgumentException("Executable name has embedded quote, " +
|
||||
"split the arguments: " + name);
|
||||
}
|
||||
// Win32 CreateProcess requires path to be normalized
|
||||
File fileToRun = new File(pathIsQuoted
|
||||
? path.substring(1, path.length() - 1)
|
||||
: path);
|
||||
File fileToRun = new File(name);
|
||||
|
||||
// From the [CreateProcess] function documentation:
|
||||
//
|
||||
@ -325,13 +356,26 @@ final class ProcessImpl extends Process {
|
||||
// sequence:..."
|
||||
//
|
||||
// In practice ANY non-existent path is extended by [.exe] extension
|
||||
// in the [CreateProcess] funcion with the only exception:
|
||||
// in the [CreateProcess] function with the only exception:
|
||||
// the path ends by (.)
|
||||
|
||||
return fileToRun.getPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* An executable is any program that is an EXE or does not have an extension
|
||||
* and the Windows createProcess will be looking for .exe.
|
||||
* The comparison is case insensitive based on the name.
|
||||
* @param executablePath the executable file
|
||||
* @return true if the path ends in .exe or does not have an extension.
|
||||
*/
|
||||
private boolean isExe(String executablePath) {
|
||||
File file = new File(executablePath);
|
||||
String upName = file.getName().toUpperCase(Locale.ROOT);
|
||||
return (upName.endsWith(".EXE") || upName.indexOf('.') < 0);
|
||||
}
|
||||
|
||||
// Old version that can be bypassed
|
||||
private boolean isShellFile(String executablePath) {
|
||||
String upPath = executablePath.toUpperCase();
|
||||
return (upPath.endsWith(".CMD") || upPath.endsWith(".BAT"));
|
||||
@ -342,6 +386,21 @@ final class ProcessImpl extends Process {
|
||||
return argbuf.append('"').append(arg).append('"').toString();
|
||||
}
|
||||
|
||||
// Count backslashes before start index of string.
|
||||
// .bat files don't include backslashes as part of the quote
|
||||
private static int countLeadingBackslash(int verificationType,
|
||||
CharSequence input, int start) {
|
||||
if (verificationType == VERIFICATION_CMD_BAT)
|
||||
return 0;
|
||||
int j;
|
||||
for (j = start - 1; j >= 0 && input.charAt(j) == BACKSLASH; j--) {
|
||||
// just scanning backwards
|
||||
}
|
||||
return (start - 1) - j; // number of BACKSLASHES
|
||||
}
|
||||
|
||||
private static final char DOUBLEQUOTE = '\"';
|
||||
private static final char BACKSLASH = '\\';
|
||||
|
||||
private final long handle;
|
||||
private final ProcessHandle processHandle;
|
||||
@ -358,15 +417,13 @@ final class ProcessImpl extends Process {
|
||||
throws IOException
|
||||
{
|
||||
String cmdstr;
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
boolean allowAmbiguousCommands = false;
|
||||
if (security == null) {
|
||||
allowAmbiguousCommands = true;
|
||||
String value = System.getProperty("jdk.lang.Process.allowAmbiguousCommands");
|
||||
if (value != null)
|
||||
allowAmbiguousCommands = !"false".equalsIgnoreCase(value);
|
||||
}
|
||||
if (allowAmbiguousCommands) {
|
||||
final SecurityManager security = System.getSecurityManager();
|
||||
final String value = GetPropertyAction.
|
||||
privilegedGetProperty("jdk.lang.Process.allowAmbiguousCommands",
|
||||
(security == null ? "true" : "false"));
|
||||
final boolean allowAmbiguousCommands = !"false".equalsIgnoreCase(value);
|
||||
|
||||
if (allowAmbiguousCommands && security == null) {
|
||||
// Legacy mode.
|
||||
|
||||
// Normalize path if possible.
|
||||
@ -413,11 +470,12 @@ final class ProcessImpl extends Process {
|
||||
// Quotation protects from interpretation of the [path] argument as
|
||||
// start of longer path with spaces. Quotation has no influence to
|
||||
// [.exe] extension heuristic.
|
||||
boolean isShell = allowAmbiguousCommands ? isShellFile(executablePath)
|
||||
: !isExe(executablePath);
|
||||
cmdstr = createCommandLine(
|
||||
// We need the extended verification procedure for CMD files.
|
||||
isShellFile(executablePath)
|
||||
? VERIFICATION_CMD_BAT
|
||||
: VERIFICATION_WIN32,
|
||||
// We need the extended verification procedures
|
||||
isShell ? VERIFICATION_CMD_BAT
|
||||
: (allowAmbiguousCommands ? VERIFICATION_WIN32 : VERIFICATION_WIN32_SAFE),
|
||||
quoteString(executablePath),
|
||||
cmd);
|
||||
}
|
||||
|
@ -1929,6 +1929,7 @@ public class Font implements java.io.Serializable
|
||||
// value is the default.
|
||||
|
||||
if (fRequestedAttributes != null) {
|
||||
try {
|
||||
values = getAttributeValues(); // init
|
||||
AttributeValues extras =
|
||||
AttributeValues.fromSerializableHashtable(fRequestedAttributes);
|
||||
@ -1938,10 +1939,13 @@ public class Font implements java.io.Serializable
|
||||
values = getAttributeValues().merge(extras);
|
||||
this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
|
||||
this.hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK);
|
||||
|
||||
} catch (Throwable t) {
|
||||
throw new IOException(t);
|
||||
} finally {
|
||||
fRequestedAttributes = null; // don't need it any more
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of glyphs in this {@code Font}. Glyph codes
|
||||
|
@ -130,7 +130,7 @@ abstract class CMap {
|
||||
|
||||
static final char noSuchChar = (char)0xfffd;
|
||||
static final int SHORTMASK = 0x0000ffff;
|
||||
static final int INTMASK = 0xffffffff;
|
||||
static final int INTMASK = 0x7fffffff;
|
||||
|
||||
static final char[][] converterMaps = new char[7][];
|
||||
|
||||
@ -919,7 +919,11 @@ abstract class CMap {
|
||||
|
||||
bbuffer.position(12);
|
||||
bbuffer.get(is32);
|
||||
nGroups = bbuffer.getInt();
|
||||
nGroups = bbuffer.getInt() & INTMASK;
|
||||
// A map group record is three uint32's making for 12 bytes total
|
||||
if (bbuffer.remaining() < (12 * (long)nGroups)) {
|
||||
throw new RuntimeException("Format 8 table exceeded");
|
||||
}
|
||||
startCharCode = new int[nGroups];
|
||||
endCharCode = new int[nGroups];
|
||||
startGlyphID = new int[nGroups];
|
||||
@ -947,9 +951,13 @@ abstract class CMap {
|
||||
|
||||
CMapFormat10(ByteBuffer bbuffer, int offset, char[] xlat) {
|
||||
|
||||
bbuffer.position(offset+12);
|
||||
firstCode = bbuffer.getInt() & INTMASK;
|
||||
entryCount = bbuffer.getInt() & INTMASK;
|
||||
bbuffer.position(offset+20);
|
||||
// each glyph is a uint16, so 2 bytes per value.
|
||||
if (bbuffer.remaining() < (2 * (long)entryCount)) {
|
||||
throw new RuntimeException("Format 10 table exceeded");
|
||||
}
|
||||
CharBuffer buffer = bbuffer.asCharBuffer();
|
||||
glyphIdArray = new char[entryCount];
|
||||
for (int i=0; i< entryCount; i++) {
|
||||
@ -989,11 +997,15 @@ abstract class CMap {
|
||||
throw new RuntimeException("xlat array for cmap fmt=12");
|
||||
}
|
||||
|
||||
numGroups = buffer.getInt(offset+12);
|
||||
buffer.position(offset+12);
|
||||
numGroups = buffer.getInt() & INTMASK;
|
||||
// A map group record is three uint32's making for 12 bytes total
|
||||
if (buffer.remaining() < (12 * (long)numGroups)) {
|
||||
throw new RuntimeException("Format 12 table exceeded");
|
||||
}
|
||||
startCharCode = new long[numGroups];
|
||||
endCharCode = new long[numGroups];
|
||||
startGlyphID = new int[numGroups];
|
||||
buffer.position(offset+16);
|
||||
buffer = buffer.slice();
|
||||
IntBuffer ibuffer = buffer.asIntBuffer();
|
||||
for (int i=0; i<numGroups; i++) {
|
||||
@ -1110,7 +1122,13 @@ abstract class CMap {
|
||||
char[][] glyphID;
|
||||
|
||||
UVS(ByteBuffer buffer, int offset) {
|
||||
numSelectors = buffer.getInt(offset+6);
|
||||
buffer.position(offset+6);
|
||||
numSelectors = buffer.getInt() & INTMASK;
|
||||
// A variation selector record is one 3 byte int + two int32's
|
||||
// making for 11 bytes per record.
|
||||
if (buffer.remaining() < (11 * (long)numSelectors)) {
|
||||
throw new RuntimeException("Variations exceed buffer");
|
||||
}
|
||||
selector = new int[numSelectors];
|
||||
numUVSMapping = new int[numSelectors];
|
||||
unicodeValue = new int[numSelectors][];
|
||||
@ -1131,6 +1149,11 @@ abstract class CMap {
|
||||
} else if (tableOffset > 0) {
|
||||
buffer.position(offset+tableOffset);
|
||||
numUVSMapping[i] = buffer.getInt() & INTMASK;
|
||||
// a UVS mapping record is one 3 byte int + uint16
|
||||
// making for 5 bytes per record.
|
||||
if (buffer.remaining() < (5 * (long)numUVSMapping[i])) {
|
||||
throw new RuntimeException("Variations exceed buffer");
|
||||
}
|
||||
unicodeValue[i] = new int[numUVSMapping[i]];
|
||||
glyphID[i] = new char[numUVSMapping[i]];
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user