提交 8f0618ad 编写于 作者: A asaha

Merge

...@@ -501,6 +501,8 @@ f09d1f6a401e25a54dad44bb7bea482e47558af5 jdk8u20-b23 ...@@ -501,6 +501,8 @@ f09d1f6a401e25a54dad44bb7bea482e47558af5 jdk8u20-b23
00cf2b6f51b9560b01030e8f4c28c466f0b21fe3 hs25.20-b23 00cf2b6f51b9560b01030e8f4c28c466f0b21fe3 hs25.20-b23
19408d5fd31c25ce60c43dd33e92b96e8df4a4ea jdk8u20-b25 19408d5fd31c25ce60c43dd33e92b96e8df4a4ea jdk8u20-b25
eaa4074a7e3975cd33ec55e6b584586e2ac681bd jdk8u20-b26 eaa4074a7e3975cd33ec55e6b584586e2ac681bd jdk8u20-b26
7c9925f21c2529a88eb64b8039cc080f60b85e01 jdk8u20-b31
7edb04063a423e278fe34a0006d25fee198f495e jdk8u20-b32
4828415ebbf11e205dcc08e97ad5ae7dd03522f9 jdk8u40-b00 4828415ebbf11e205dcc08e97ad5ae7dd03522f9 jdk8u40-b00
d952af8cf67dd1e7ab5fec9a299c6c6dafd1863e hs25.40-b01 d952af8cf67dd1e7ab5fec9a299c6c6dafd1863e hs25.40-b01
f0afba33c928ddaa2d5f003b90d683c143f78ea3 hs25.40-b02 f0afba33c928ddaa2d5f003b90d683c143f78ea3 hs25.40-b02
...@@ -544,6 +546,13 @@ e62c06b887310b5bd23be9b817a9a6f0daf0d0e1 jdk8u25-b15 ...@@ -544,6 +546,13 @@ e62c06b887310b5bd23be9b817a9a6f0daf0d0e1 jdk8u25-b15
6467bdd4d22d8b140844dc847c43b9ba7cb0bbd1 jdk8u25-b16 6467bdd4d22d8b140844dc847c43b9ba7cb0bbd1 jdk8u25-b16
28b50d07f6f8c5a567b6a25e95a423948114a004 jdk8u25-b17 28b50d07f6f8c5a567b6a25e95a423948114a004 jdk8u25-b17
639abc668bfe995dba811dd35411b9ea8a9041cd jdk8u25-b18 639abc668bfe995dba811dd35411b9ea8a9041cd jdk8u25-b18
c3528699fb33fe3eb1d117504184ae7ab2507aa1 jdk8u25-b31
5bb683bbe2c74876d585b5c3232fc3aab7b23e97 jdk8u31-b00
5bb686ae3b89f8aa1c74331b2d24e2a5ebd43448 jdk8u31-b01
087678da96603c9705b38b6cc4a6569ac7b4420a jdk8u31-b02
401cbaa475b4efe53153119ab87a82b217980a7f jdk8u31-b03
060cdf93040c1bfa5fdf580da5e9999042632cc8 jdk8u31-b04
6e56d7f1634f6c4cd4196e699c06e6ca2e6d6efb jdk8u31-b05
1b3abbeee961dee49780c0e4af5337feb918c555 jdk8u40-b10 1b3abbeee961dee49780c0e4af5337feb918c555 jdk8u40-b10
f10fe402dfb1543723b4b117a7cba3ea3d4159f1 hs25.40-b15 f10fe402dfb1543723b4b117a7cba3ea3d4159f1 hs25.40-b15
99372b2fee0eb8b3452f47230e84aa6e97003184 jdk8u40-b11 99372b2fee0eb8b3452f47230e84aa6e97003184 jdk8u40-b11
# #
# Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
# #
# Don't put quotes (fail windows build). # Don't put quotes (fail windows build).
HOTSPOT_VM_COPYRIGHT=Copyright 2014 HOTSPOT_VM_COPYRIGHT=Copyright 2015
HS_MAJOR_VER=25 HS_MAJOR_VER=25
HS_MINOR_VER=40 HS_MINOR_VER=40
......
...@@ -89,8 +89,8 @@ class BCEscapeAnalyzer::StateInfo { ...@@ -89,8 +89,8 @@ class BCEscapeAnalyzer::StateInfo {
public: public:
ArgumentMap *_vars; ArgumentMap *_vars;
ArgumentMap *_stack; ArgumentMap *_stack;
short _stack_height; int _stack_height;
short _max_stack; int _max_stack;
bool _initialized; bool _initialized;
ArgumentMap empty_map; ArgumentMap empty_map;
......
...@@ -1908,11 +1908,12 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) { ...@@ -1908,11 +1908,12 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
InstanceKlass::cast(WK_KLASS(Reference_klass))->set_reference_type(REF_OTHER); InstanceKlass::cast(WK_KLASS(Reference_klass))->set_reference_type(REF_OTHER);
InstanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(Reference_klass)); InstanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(Reference_klass));
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(PhantomReference_klass), scan, CHECK); initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Cleaner_klass), scan, CHECK);
InstanceKlass::cast(WK_KLASS(SoftReference_klass))->set_reference_type(REF_SOFT); InstanceKlass::cast(WK_KLASS(SoftReference_klass))->set_reference_type(REF_SOFT);
InstanceKlass::cast(WK_KLASS(WeakReference_klass))->set_reference_type(REF_WEAK); InstanceKlass::cast(WK_KLASS(WeakReference_klass))->set_reference_type(REF_WEAK);
InstanceKlass::cast(WK_KLASS(FinalReference_klass))->set_reference_type(REF_FINAL); InstanceKlass::cast(WK_KLASS(FinalReference_klass))->set_reference_type(REF_FINAL);
InstanceKlass::cast(WK_KLASS(PhantomReference_klass))->set_reference_type(REF_PHANTOM); InstanceKlass::cast(WK_KLASS(PhantomReference_klass))->set_reference_type(REF_PHANTOM);
InstanceKlass::cast(WK_KLASS(Cleaner_klass))->set_reference_type(REF_CLEANER);
// JSR 292 classes // JSR 292 classes
WKID jsr292_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass); WKID jsr292_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
......
...@@ -128,6 +128,7 @@ class Ticks; ...@@ -128,6 +128,7 @@ class Ticks;
do_klass(WeakReference_klass, java_lang_ref_WeakReference, Pre ) \ do_klass(WeakReference_klass, java_lang_ref_WeakReference, Pre ) \
do_klass(FinalReference_klass, java_lang_ref_FinalReference, Pre ) \ do_klass(FinalReference_klass, java_lang_ref_FinalReference, Pre ) \
do_klass(PhantomReference_klass, java_lang_ref_PhantomReference, Pre ) \ do_klass(PhantomReference_klass, java_lang_ref_PhantomReference, Pre ) \
do_klass(Cleaner_klass, sun_misc_Cleaner, Pre ) \
do_klass(Finalizer_klass, java_lang_ref_Finalizer, Pre ) \ do_klass(Finalizer_klass, java_lang_ref_Finalizer, Pre ) \
\ \
do_klass(Thread_klass, java_lang_Thread, Pre ) \ do_klass(Thread_klass, java_lang_Thread, Pre ) \
......
...@@ -1553,14 +1553,14 @@ void ClassVerifier::verify_method(methodHandle m, TRAPS) { ...@@ -1553,14 +1553,14 @@ void ClassVerifier::verify_method(methodHandle m, TRAPS) {
case Bytecodes::_invokespecial : case Bytecodes::_invokespecial :
case Bytecodes::_invokestatic : case Bytecodes::_invokestatic :
verify_invoke_instructions( verify_invoke_instructions(
&bcs, code_length, &current_frame, &bcs, code_length, &current_frame, (bci >= ex_min && bci < ex_max),
&this_uninit, return_type, cp, CHECK_VERIFY(this)); &this_uninit, return_type, cp, &stackmap_table, CHECK_VERIFY(this));
no_control_flow = false; break; no_control_flow = false; break;
case Bytecodes::_invokeinterface : case Bytecodes::_invokeinterface :
case Bytecodes::_invokedynamic : case Bytecodes::_invokedynamic :
verify_invoke_instructions( verify_invoke_instructions(
&bcs, code_length, &current_frame, &bcs, code_length, &current_frame, (bci >= ex_min && bci < ex_max),
&this_uninit, return_type, cp, CHECK_VERIFY(this)); &this_uninit, return_type, cp, &stackmap_table, CHECK_VERIFY(this));
no_control_flow = false; break; no_control_flow = false; break;
case Bytecodes::_new : case Bytecodes::_new :
{ {
...@@ -2408,8 +2408,9 @@ bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) { ...@@ -2408,8 +2408,9 @@ bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) {
void ClassVerifier::verify_invoke_init( void ClassVerifier::verify_invoke_init(
RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type, RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type,
StackMapFrame* current_frame, u4 code_length, bool *this_uninit, StackMapFrame* current_frame, u4 code_length, bool in_try_block,
constantPoolHandle cp, TRAPS) { bool *this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table,
TRAPS) {
u2 bci = bcs->bci(); u2 bci = bcs->bci();
VerificationType type = current_frame->pop_stack( VerificationType type = current_frame->pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this)); VerificationType::reference_check(), CHECK_VERIFY(this));
...@@ -2425,28 +2426,36 @@ void ClassVerifier::verify_invoke_init( ...@@ -2425,28 +2426,36 @@ void ClassVerifier::verify_invoke_init(
return; return;
} }
// Check if this call is done from inside of a TRY block. If so, make // If this invokespecial call is done from inside of a TRY block then make
// sure that all catch clause paths end in a throw. Otherwise, this // sure that all catch clause paths end in a throw. Otherwise, this can
// can result in returning an incomplete object. // result in returning an incomplete object.
ExceptionTable exhandlers(_method()); if (in_try_block) {
int exlength = exhandlers.length(); ExceptionTable exhandlers(_method());
for(int i = 0; i < exlength; i++) { int exlength = exhandlers.length();
u2 start_pc = exhandlers.start_pc(i); for(int i = 0; i < exlength; i++) {
u2 end_pc = exhandlers.end_pc(i); u2 start_pc = exhandlers.start_pc(i);
u2 end_pc = exhandlers.end_pc(i);
if (bci >= start_pc && bci < end_pc) {
if (!ends_in_athrow(exhandlers.handler_pc(i))) { if (bci >= start_pc && bci < end_pc) {
verify_error(ErrorContext::bad_code(bci), if (!ends_in_athrow(exhandlers.handler_pc(i))) {
"Bad <init> method call from after the start of a try block"); verify_error(ErrorContext::bad_code(bci),
return; "Bad <init> method call from after the start of a try block");
} else if (VerboseVerification) { return;
ResourceMark rm; } else if (VerboseVerification) {
tty->print_cr( ResourceMark rm;
"Survived call to ends_in_athrow(): %s", tty->print_cr(
current_class()->name()->as_C_string()); "Survived call to ends_in_athrow(): %s",
current_class()->name()->as_C_string());
}
} }
} }
}
// Check the exception handler target stackmaps with the locals from the
// incoming stackmap (before initialize_object() changes them to outgoing
// state).
verify_exception_handler_targets(bci, true, current_frame,
stackmap_table, CHECK_VERIFY(this));
} // in_try_block
current_frame->initialize_object(type, current_type()); current_frame->initialize_object(type, current_type());
*this_uninit = true; *this_uninit = true;
...@@ -2500,6 +2509,13 @@ void ClassVerifier::verify_invoke_init( ...@@ -2500,6 +2509,13 @@ void ClassVerifier::verify_invoke_init(
} }
} }
} }
// Check the exception handler target stackmaps with the locals from the
// incoming stackmap (before initialize_object() changes them to outgoing
// state).
if (in_try_block) {
verify_exception_handler_targets(bci, *this_uninit, current_frame,
stackmap_table, CHECK_VERIFY(this));
}
current_frame->initialize_object(type, new_class_type); current_frame->initialize_object(type, new_class_type);
} else { } else {
verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx()), verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx()),
...@@ -2528,8 +2544,8 @@ bool ClassVerifier::is_same_or_direct_interface( ...@@ -2528,8 +2544,8 @@ bool ClassVerifier::is_same_or_direct_interface(
void ClassVerifier::verify_invoke_instructions( void ClassVerifier::verify_invoke_instructions(
RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame, RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
bool *this_uninit, VerificationType return_type, bool in_try_block, bool *this_uninit, VerificationType return_type,
constantPoolHandle cp, TRAPS) { constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS) {
// Make sure the constant pool item is the right type // Make sure the constant pool item is the right type
u2 index = bcs->get_index_u2(); u2 index = bcs->get_index_u2();
Bytecodes::Code opcode = bcs->raw_code(); Bytecodes::Code opcode = bcs->raw_code();
...@@ -2699,7 +2715,8 @@ void ClassVerifier::verify_invoke_instructions( ...@@ -2699,7 +2715,8 @@ void ClassVerifier::verify_invoke_instructions(
opcode != Bytecodes::_invokedynamic) { opcode != Bytecodes::_invokedynamic) {
if (method_name == vmSymbols::object_initializer_name()) { // <init> method if (method_name == vmSymbols::object_initializer_name()) { // <init> method
verify_invoke_init(bcs, index, ref_class_type, current_frame, verify_invoke_init(bcs, index, ref_class_type, current_frame,
code_length, this_uninit, cp, CHECK_VERIFY(this)); code_length, in_try_block, this_uninit, cp, stackmap_table,
CHECK_VERIFY(this));
} else { // other methods } else { // other methods
// Ensures that target class is assignable to method class. // Ensures that target class is assignable to method class.
if (opcode == Bytecodes::_invokespecial) { if (opcode == Bytecodes::_invokespecial) {
......
...@@ -301,8 +301,9 @@ class ClassVerifier : public StackObj { ...@@ -301,8 +301,9 @@ class ClassVerifier : public StackObj {
void verify_invoke_init( void verify_invoke_init(
RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type, RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type,
StackMapFrame* current_frame, u4 code_length, bool* this_uninit, StackMapFrame* current_frame, u4 code_length, bool in_try_block,
constantPoolHandle cp, TRAPS); bool* this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table,
TRAPS);
// Used by ends_in_athrow() to push all handlers that contain bci onto // Used by ends_in_athrow() to push all handlers that contain bci onto
// the handler_stack, if the handler is not already on the stack. // the handler_stack, if the handler is not already on the stack.
...@@ -316,8 +317,8 @@ class ClassVerifier : public StackObj { ...@@ -316,8 +317,8 @@ class ClassVerifier : public StackObj {
void verify_invoke_instructions( void verify_invoke_instructions(
RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame, RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
bool* this_uninit, VerificationType return_type, bool in_try_block, bool* this_uninit, VerificationType return_type,
constantPoolHandle cp, TRAPS); constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS);
VerificationType get_newarray_type(u2 index, u2 bci, TRAPS); VerificationType get_newarray_type(u2 index, u2 bci, TRAPS);
void verify_anewarray(u2 bci, u2 index, constantPoolHandle cp, void verify_anewarray(u2 bci, u2 index, constantPoolHandle cp,
......
...@@ -79,6 +79,7 @@ ...@@ -79,6 +79,7 @@
template(java_lang_ref_WeakReference, "java/lang/ref/WeakReference") \ template(java_lang_ref_WeakReference, "java/lang/ref/WeakReference") \
template(java_lang_ref_FinalReference, "java/lang/ref/FinalReference") \ template(java_lang_ref_FinalReference, "java/lang/ref/FinalReference") \
template(java_lang_ref_PhantomReference, "java/lang/ref/PhantomReference") \ template(java_lang_ref_PhantomReference, "java/lang/ref/PhantomReference") \
template(sun_misc_Cleaner, "sun/misc/Cleaner") \
template(java_lang_ref_Finalizer, "java/lang/ref/Finalizer") \ template(java_lang_ref_Finalizer, "java/lang/ref/Finalizer") \
template(java_lang_reflect_AccessibleObject, "java/lang/reflect/AccessibleObject") \ template(java_lang_reflect_AccessibleObject, "java/lang/reflect/AccessibleObject") \
template(java_lang_reflect_Method, "java/lang/reflect/Method") \ template(java_lang_reflect_Method, "java/lang/reflect/Method") \
......
...@@ -738,7 +738,7 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, ...@@ -738,7 +738,7 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen,
// Support for parallelizing survivor space rescan // Support for parallelizing survivor space rescan
if ((CMSParallelRemarkEnabled && CMSParallelSurvivorRemarkEnabled) || CMSParallelInitialMarkEnabled) { if ((CMSParallelRemarkEnabled && CMSParallelSurvivorRemarkEnabled) || CMSParallelInitialMarkEnabled) {
const size_t max_plab_samples = const size_t max_plab_samples =
((DefNewGeneration*)_young_gen)->max_survivor_size()/MinTLABSize; ((DefNewGeneration*)_young_gen)->max_survivor_size() / plab_sample_minimum_size();
_survivor_plab_array = NEW_C_HEAP_ARRAY(ChunkArray, ParallelGCThreads, mtGC); _survivor_plab_array = NEW_C_HEAP_ARRAY(ChunkArray, ParallelGCThreads, mtGC);
_survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, 2*max_plab_samples, mtGC); _survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, 2*max_plab_samples, mtGC);
...@@ -796,6 +796,12 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, ...@@ -796,6 +796,12 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen,
_inter_sweep_timer.start(); // start of time _inter_sweep_timer.start(); // start of time
} }
size_t CMSCollector::plab_sample_minimum_size() {
// The default value of MinTLABSize is 2k, but there is
// no way to get the default value if the flag has been overridden.
return MAX2(ThreadLocalAllocBuffer::min_size() * HeapWordSize, 2 * K);
}
const char* ConcurrentMarkSweepGeneration::name() const { const char* ConcurrentMarkSweepGeneration::name() const {
return "concurrent mark-sweep generation"; return "concurrent mark-sweep generation";
} }
......
...@@ -764,6 +764,10 @@ class CMSCollector: public CHeapObj<mtGC> { ...@@ -764,6 +764,10 @@ class CMSCollector: public CHeapObj<mtGC> {
size_t* _cursor; size_t* _cursor;
ChunkArray* _survivor_plab_array; ChunkArray* _survivor_plab_array;
// A bounded minimum size of PLABs, should not return too small values since
// this will affect the size of the data structures used for parallel young gen rescan
size_t plab_sample_minimum_size();
// Support for marking stack overflow handling // Support for marking stack overflow handling
bool take_from_overflow_list(size_t num, CMSMarkStack* to_stack); bool take_from_overflow_list(size_t num, CMSMarkStack* to_stack);
bool par_take_from_overflow_list(size_t num, bool par_take_from_overflow_list(size_t num,
......
/* /*
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -47,6 +47,13 @@ public: ...@@ -47,6 +47,13 @@ public:
// active field set to true. // active field set to true.
PtrQueue(qset_, perm, true /* active */) { } PtrQueue(qset_, perm, true /* active */) { }
// Flush before destroying; queue may be used to capture pending work while
// doing something else, with auto-flush on completion.
~DirtyCardQueue() { if (!is_permanent()) flush(); }
// Process queue entries and release resources.
void flush() { flush_impl(); }
// Apply the closure to all elements, and reset the index to make the // Apply the closure to all elements, and reset the index to make the
// buffer empty. If a closure application returns "false", return // buffer empty. If a closure application returns "false", return
// "false" immediately, halting the iteration. If "consume" is true, // "false" immediately, halting the iteration. If "consume" is true,
......
/* /*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -31,11 +31,15 @@ ...@@ -31,11 +31,15 @@
#include "runtime/thread.inline.hpp" #include "runtime/thread.inline.hpp"
PtrQueue::PtrQueue(PtrQueueSet* qset, bool perm, bool active) : PtrQueue::PtrQueue(PtrQueueSet* qset, bool perm, bool active) :
_qset(qset), _buf(NULL), _index(0), _active(active), _qset(qset), _buf(NULL), _index(0), _sz(0), _active(active),
_perm(perm), _lock(NULL) _perm(perm), _lock(NULL)
{} {}
void PtrQueue::flush() { PtrQueue::~PtrQueue() {
assert(_perm || (_buf == NULL), "queue must be flushed before delete");
}
void PtrQueue::flush_impl() {
if (!_perm && _buf != NULL) { if (!_perm && _buf != NULL) {
if (_index == _sz) { if (_index == _sz) {
// No work to do. // No work to do.
......
/* /*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -65,15 +65,18 @@ protected: ...@@ -65,15 +65,18 @@ protected:
Mutex* _lock; Mutex* _lock;
PtrQueueSet* qset() { return _qset; } PtrQueueSet* qset() { return _qset; }
bool is_permanent() const { return _perm; }
// Process queue entries and release resources, if not permanent.
void flush_impl();
public: public:
// Initialize this queue to contain a null buffer, and be part of the // Initialize this queue to contain a null buffer, and be part of the
// given PtrQueueSet. // given PtrQueueSet.
PtrQueue(PtrQueueSet* qset, bool perm = false, bool active = false); PtrQueue(PtrQueueSet* qset, bool perm = false, bool active = false);
// Release any contained resources.
virtual void flush(); // Requires queue flushed or permanent.
// Calls flush() when destroyed. ~PtrQueue();
~PtrQueue() { flush(); }
// Associate a lock with a ptr queue. // Associate a lock with a ptr queue.
void set_lock(Mutex* lock) { _lock = lock; } void set_lock(Mutex* lock) { _lock = lock; }
......
...@@ -39,7 +39,7 @@ void ObjPtrQueue::flush() { ...@@ -39,7 +39,7 @@ void ObjPtrQueue::flush() {
// first before we flush it, otherwise we might end up with an // first before we flush it, otherwise we might end up with an
// enqueued buffer with refs into the CSet which breaks our invariants. // enqueued buffer with refs into the CSet which breaks our invariants.
filter(); filter();
PtrQueue::flush(); flush_impl();
} }
// This method removes entries from an SATB buffer that will not be // This method removes entries from an SATB buffer that will not be
......
/* /*
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -60,9 +60,8 @@ public: ...@@ -60,9 +60,8 @@ public:
// field to true. This is done in JavaThread::initialize_queues(). // field to true. This is done in JavaThread::initialize_queues().
PtrQueue(qset, perm, false /* active */) { } PtrQueue(qset, perm, false /* active */) { }
// Overrides PtrQueue::flush() so that it can filter the buffer // Process queue entries and free resources.
// before it is flushed. void flush();
virtual void flush();
// Overrides PtrQueue::should_enqueue_buffer(). See the method's // Overrides PtrQueue::should_enqueue_buffer(). See the method's
// definition for more information. // definition for more information.
......
...@@ -63,7 +63,8 @@ public: ...@@ -63,7 +63,8 @@ public:
virtual ~ParGCAllocBuffer() {} virtual ~ParGCAllocBuffer() {}
static const size_t min_size() { static const size_t min_size() {
return ThreadLocalAllocBuffer::min_size(); // Make sure that we return something that is larger than AlignmentReserve
return align_object_size(MAX2(MinTLABSize / HeapWordSize, (uintx)oopDesc::header_size())) + AlignmentReserve;
} }
static const size_t max_size() { static const size_t max_size() {
......
...@@ -118,6 +118,7 @@ ReferenceProcessor::ReferenceProcessor(MemRegion span, ...@@ -118,6 +118,7 @@ ReferenceProcessor::ReferenceProcessor(MemRegion span,
_discoveredWeakRefs = &_discoveredSoftRefs[_max_num_q]; _discoveredWeakRefs = &_discoveredSoftRefs[_max_num_q];
_discoveredFinalRefs = &_discoveredWeakRefs[_max_num_q]; _discoveredFinalRefs = &_discoveredWeakRefs[_max_num_q];
_discoveredPhantomRefs = &_discoveredFinalRefs[_max_num_q]; _discoveredPhantomRefs = &_discoveredFinalRefs[_max_num_q];
_discoveredCleanerRefs = &_discoveredPhantomRefs[_max_num_q];
// Initialize all entries to NULL // Initialize all entries to NULL
for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) {
...@@ -246,6 +247,13 @@ ReferenceProcessorStats ReferenceProcessor::process_discovered_references( ...@@ -246,6 +247,13 @@ ReferenceProcessorStats ReferenceProcessor::process_discovered_references(
phantom_count = phantom_count =
process_discovered_reflist(_discoveredPhantomRefs, NULL, false, process_discovered_reflist(_discoveredPhantomRefs, NULL, false,
is_alive, keep_alive, complete_gc, task_executor); is_alive, keep_alive, complete_gc, task_executor);
// Process cleaners, but include them in phantom statistics. We expect
// Cleaner references to be temporary, and don't want to deal with
// possible incompatibilities arising from making it more visible.
phantom_count +=
process_discovered_reflist(_discoveredCleanerRefs, NULL, false,
is_alive, keep_alive, complete_gc, task_executor);
} }
// Weak global JNI references. It would make more sense (semantically) to // Weak global JNI references. It would make more sense (semantically) to
...@@ -883,6 +891,7 @@ void ReferenceProcessor::balance_all_queues() { ...@@ -883,6 +891,7 @@ void ReferenceProcessor::balance_all_queues() {
balance_queues(_discoveredWeakRefs); balance_queues(_discoveredWeakRefs);
balance_queues(_discoveredFinalRefs); balance_queues(_discoveredFinalRefs);
balance_queues(_discoveredPhantomRefs); balance_queues(_discoveredPhantomRefs);
balance_queues(_discoveredCleanerRefs);
} }
size_t size_t
...@@ -1042,6 +1051,9 @@ inline DiscoveredList* ReferenceProcessor::get_discovered_list(ReferenceType rt) ...@@ -1042,6 +1051,9 @@ inline DiscoveredList* ReferenceProcessor::get_discovered_list(ReferenceType rt)
case REF_PHANTOM: case REF_PHANTOM:
list = &_discoveredPhantomRefs[id]; list = &_discoveredPhantomRefs[id];
break; break;
case REF_CLEANER:
list = &_discoveredCleanerRefs[id];
break;
case REF_NONE: case REF_NONE:
// we should not reach here if we are an InstanceRefKlass // we should not reach here if we are an InstanceRefKlass
default: default:
...@@ -1307,6 +1319,17 @@ void ReferenceProcessor::preclean_discovered_references( ...@@ -1307,6 +1319,17 @@ void ReferenceProcessor::preclean_discovered_references(
preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive, preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive,
keep_alive, complete_gc, yield); keep_alive, complete_gc, yield);
} }
// Cleaner references. Included in timing for phantom references. We
// expect Cleaner references to be temporary, and don't want to deal with
// possible incompatibilities arising from making it more visible.
for (uint i = 0; i < _max_num_q; i++) {
if (yield->should_return()) {
return;
}
preclean_discovered_reflist(_discoveredCleanerRefs[i], is_alive,
keep_alive, complete_gc, yield);
}
} }
} }
...@@ -1375,6 +1398,7 @@ const char* ReferenceProcessor::list_name(uint i) { ...@@ -1375,6 +1398,7 @@ const char* ReferenceProcessor::list_name(uint i) {
case 1: return "WeakRef"; case 1: return "WeakRef";
case 2: return "FinalRef"; case 2: return "FinalRef";
case 3: return "PhantomRef"; case 3: return "PhantomRef";
case 4: return "CleanerRef";
} }
ShouldNotReachHere(); ShouldNotReachHere();
return NULL; return NULL;
......
...@@ -264,9 +264,10 @@ class ReferenceProcessor : public CHeapObj<mtGC> { ...@@ -264,9 +264,10 @@ class ReferenceProcessor : public CHeapObj<mtGC> {
DiscoveredList* _discoveredWeakRefs; DiscoveredList* _discoveredWeakRefs;
DiscoveredList* _discoveredFinalRefs; DiscoveredList* _discoveredFinalRefs;
DiscoveredList* _discoveredPhantomRefs; DiscoveredList* _discoveredPhantomRefs;
DiscoveredList* _discoveredCleanerRefs;
public: public:
static int number_of_subclasses_of_ref() { return (REF_PHANTOM - REF_OTHER); } static int number_of_subclasses_of_ref() { return (REF_CLEANER - REF_OTHER); }
uint num_q() { return _num_q; } uint num_q() { return _num_q; }
uint max_num_q() { return _max_num_q; } uint max_num_q() { return _max_num_q; }
......
...@@ -35,7 +35,8 @@ enum ReferenceType { ...@@ -35,7 +35,8 @@ enum ReferenceType {
REF_SOFT, // Subclass of java/lang/ref/SoftReference REF_SOFT, // Subclass of java/lang/ref/SoftReference
REF_WEAK, // Subclass of java/lang/ref/WeakReference REF_WEAK, // Subclass of java/lang/ref/WeakReference
REF_FINAL, // Subclass of java/lang/ref/FinalReference REF_FINAL, // Subclass of java/lang/ref/FinalReference
REF_PHANTOM // Subclass of java/lang/ref/PhantomReference REF_PHANTOM, // Subclass of java/lang/ref/PhantomReference
REF_CLEANER // Subclass of sun/misc/Cleaner
}; };
#endif // SHARE_VM_MEMORY_REFRERENCETYPE_HPP #endif // SHARE_VM_MEMORY_REFRERENCETYPE_HPP
...@@ -235,22 +235,19 @@ void ThreadLocalAllocBuffer::startup_initialization() { ...@@ -235,22 +235,19 @@ void ThreadLocalAllocBuffer::startup_initialization() {
} }
size_t ThreadLocalAllocBuffer::initial_desired_size() { size_t ThreadLocalAllocBuffer::initial_desired_size() {
size_t init_sz; size_t init_sz = 0;
if (TLABSize > 0) { if (TLABSize > 0) {
init_sz = MIN2(TLABSize / HeapWordSize, max_size()); init_sz = TLABSize / HeapWordSize;
} else if (global_stats() == NULL) { } else if (global_stats() != NULL) {
// Startup issue - main thread initialized before heap initialized.
init_sz = min_size();
} else {
// Initial size is a function of the average number of allocating threads. // Initial size is a function of the average number of allocating threads.
unsigned nof_threads = global_stats()->allocating_threads_avg(); unsigned nof_threads = global_stats()->allocating_threads_avg();
init_sz = (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize) / init_sz = (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize) /
(nof_threads * target_refills()); (nof_threads * target_refills());
init_sz = align_object_size(init_sz); init_sz = align_object_size(init_sz);
init_sz = MIN2(MAX2(init_sz, min_size()), max_size());
} }
init_sz = MIN2(MAX2(init_sz, min_size()), max_size());
return init_sz; return init_sz;
} }
......
...@@ -105,7 +105,7 @@ public: ...@@ -105,7 +105,7 @@ public:
// do nothing. tlabs must be inited by initialize() calls // do nothing. tlabs must be inited by initialize() calls
} }
static const size_t min_size() { return align_object_size(MinTLABSize / HeapWordSize); } static const size_t min_size() { return align_object_size(MinTLABSize / HeapWordSize) + alignment_reserve(); }
static const size_t max_size() { assert(_max_size != 0, "max_size not set up"); return _max_size; } static const size_t max_size() { assert(_max_size != 0, "max_size not set up"); return _max_size; }
static void set_max_size(size_t max_size) { _max_size = max_size; } static void set_max_size(size_t max_size) { _max_size = max_size; }
......
...@@ -671,6 +671,7 @@ typedef BinaryTreeDictionary<Metablock, FreeList<Metablock> > MetablockTreeDicti ...@@ -671,6 +671,7 @@ typedef BinaryTreeDictionary<Metablock, FreeList<Metablock> > MetablockTreeDicti
static_field(SystemDictionary, WK_KLASS(WeakReference_klass), Klass*) \ static_field(SystemDictionary, WK_KLASS(WeakReference_klass), Klass*) \
static_field(SystemDictionary, WK_KLASS(FinalReference_klass), Klass*) \ static_field(SystemDictionary, WK_KLASS(FinalReference_klass), Klass*) \
static_field(SystemDictionary, WK_KLASS(PhantomReference_klass), Klass*) \ static_field(SystemDictionary, WK_KLASS(PhantomReference_klass), Klass*) \
static_field(SystemDictionary, WK_KLASS(Cleaner_klass), Klass*) \
static_field(SystemDictionary, WK_KLASS(Finalizer_klass), Klass*) \ static_field(SystemDictionary, WK_KLASS(Finalizer_klass), Klass*) \
static_field(SystemDictionary, WK_KLASS(Thread_klass), Klass*) \ static_field(SystemDictionary, WK_KLASS(Thread_klass), Klass*) \
static_field(SystemDictionary, WK_KLASS(ThreadGroup_klass), Klass*) \ static_field(SystemDictionary, WK_KLASS(ThreadGroup_klass), Klass*) \
......
...@@ -41,6 +41,8 @@ class defaultStream : public xmlTextStream { ...@@ -41,6 +41,8 @@ class defaultStream : public xmlTextStream {
void init(); void init();
void init_log(); void init_log();
fileStream* open_file(const char* log_name);
void start_log();
void finish_log(); void finish_log();
void finish_log_on_error(char *buf, int buflen); void finish_log_on_error(char *buf, int buflen);
public: public:
......
...@@ -370,7 +370,6 @@ extern Mutex* tty_lock; ...@@ -370,7 +370,6 @@ extern Mutex* tty_lock;
#define EXTRACHARLEN 32 #define EXTRACHARLEN 32
#define CURRENTAPPX ".current" #define CURRENTAPPX ".current"
#define FILENAMEBUFLEN 1024
// convert YYYY-MM-DD HH:MM:SS to YYYY-MM-DD_HH-MM-SS // convert YYYY-MM-DD HH:MM:SS to YYYY-MM-DD_HH-MM-SS
char* get_datetime_string(char *buf, size_t len) { char* get_datetime_string(char *buf, size_t len) {
os::local_time_string(buf, len); os::local_time_string(buf, len);
...@@ -404,7 +403,6 @@ static const char* make_log_name_internal(const char* log_name, const char* forc ...@@ -404,7 +403,6 @@ static const char* make_log_name_internal(const char* log_name, const char* forc
buffer_length = strlen(log_name) + 1; buffer_length = strlen(log_name) + 1;
} }
// const char* star = strchr(basename, '*');
const char* pts = strstr(basename, "%p"); const char* pts = strstr(basename, "%p");
int pid_pos = (pts == NULL) ? -1 : (pts - nametail); int pid_pos = (pts == NULL) ? -1 : (pts - nametail);
...@@ -419,6 +417,11 @@ static const char* make_log_name_internal(const char* log_name, const char* forc ...@@ -419,6 +417,11 @@ static const char* make_log_name_internal(const char* log_name, const char* forc
buffer_length += strlen(tms); buffer_length += strlen(tms);
} }
// File name is too long.
if (buffer_length > JVM_MAXPATHLEN) {
return NULL;
}
// Create big enough buffer. // Create big enough buffer.
char *buf = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal); char *buf = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal);
...@@ -492,46 +495,88 @@ static const char* make_log_name(const char* log_name, const char* force_directo ...@@ -492,46 +495,88 @@ static const char* make_log_name(const char* log_name, const char* force_directo
void test_loggc_filename() { void test_loggc_filename() {
int pid; int pid;
char tms[32]; char tms[32];
char i_result[FILENAMEBUFLEN]; char i_result[JVM_MAXPATHLEN];
const char* o_result; const char* o_result;
get_datetime_string(tms, sizeof(tms)); get_datetime_string(tms, sizeof(tms));
pid = os::current_process_id(); pid = os::current_process_id();
// test.log // test.log
jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test.log", tms); jio_snprintf(i_result, JVM_MAXPATHLEN, "test.log", tms);
o_result = make_log_name_internal("test.log", NULL, pid, tms); o_result = make_log_name_internal("test.log", NULL, pid, tms);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test.log\", NULL)"); assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test.log\", NULL)");
FREE_C_HEAP_ARRAY(char, o_result, mtInternal); FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
// test-%t-%p.log // test-%t-%p.log
jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test-%s-pid%u.log", tms, pid); jio_snprintf(i_result, JVM_MAXPATHLEN, "test-%s-pid%u.log", tms, pid);
o_result = make_log_name_internal("test-%t-%p.log", NULL, pid, tms); o_result = make_log_name_internal("test-%t-%p.log", NULL, pid, tms);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t-%%p.log\", NULL)"); assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t-%%p.log\", NULL)");
FREE_C_HEAP_ARRAY(char, o_result, mtInternal); FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
// test-%t%p.log // test-%t%p.log
jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test-%spid%u.log", tms, pid); jio_snprintf(i_result, JVM_MAXPATHLEN, "test-%spid%u.log", tms, pid);
o_result = make_log_name_internal("test-%t%p.log", NULL, pid, tms); o_result = make_log_name_internal("test-%t%p.log", NULL, pid, tms);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t%%p.log\", NULL)"); assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t%%p.log\", NULL)");
FREE_C_HEAP_ARRAY(char, o_result, mtInternal); FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
// %p%t.log // %p%t.log
jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "pid%u%s.log", pid, tms); jio_snprintf(i_result, JVM_MAXPATHLEN, "pid%u%s.log", pid, tms);
o_result = make_log_name_internal("%p%t.log", NULL, pid, tms); o_result = make_log_name_internal("%p%t.log", NULL, pid, tms);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p%%t.log\", NULL)"); assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p%%t.log\", NULL)");
FREE_C_HEAP_ARRAY(char, o_result, mtInternal); FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
// %p-test.log // %p-test.log
jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "pid%u-test.log", pid); jio_snprintf(i_result, JVM_MAXPATHLEN, "pid%u-test.log", pid);
o_result = make_log_name_internal("%p-test.log", NULL, pid, tms); o_result = make_log_name_internal("%p-test.log", NULL, pid, tms);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p-test.log\", NULL)"); assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p-test.log\", NULL)");
FREE_C_HEAP_ARRAY(char, o_result, mtInternal); FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
// %t.log // %t.log
jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "%s.log", tms); jio_snprintf(i_result, JVM_MAXPATHLEN, "%s.log", tms);
o_result = make_log_name_internal("%t.log", NULL, pid, tms); o_result = make_log_name_internal("%t.log", NULL, pid, tms);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%t.log\", NULL)"); assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%t.log\", NULL)");
FREE_C_HEAP_ARRAY(char, o_result, mtInternal); FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
{
// longest filename
char longest_name[JVM_MAXPATHLEN];
memset(longest_name, 'a', sizeof(longest_name));
longest_name[JVM_MAXPATHLEN - 1] = '\0';
o_result = make_log_name_internal((const char*)&longest_name, NULL, pid, tms);
assert(strcmp(longest_name, o_result) == 0, err_msg("longest name does not match. expected '%s' but got '%s'", longest_name, o_result));
FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
}
{
// too long file name
char too_long_name[JVM_MAXPATHLEN + 100];
int too_long_length = sizeof(too_long_name);
memset(too_long_name, 'a', too_long_length);
too_long_name[too_long_length - 1] = '\0';
o_result = make_log_name_internal((const char*)&too_long_name, NULL, pid, tms);
assert(o_result == NULL, err_msg("Too long file name should return NULL, but got '%s'", o_result));
}
{
// too long with timestamp
char longest_name[JVM_MAXPATHLEN];
memset(longest_name, 'a', JVM_MAXPATHLEN);
longest_name[JVM_MAXPATHLEN - 3] = '%';
longest_name[JVM_MAXPATHLEN - 2] = 't';
longest_name[JVM_MAXPATHLEN - 1] = '\0';
o_result = make_log_name_internal((const char*)&longest_name, NULL, pid, tms);
assert(o_result == NULL, err_msg("Too long file name after timestamp expansion should return NULL, but got '%s'", o_result));
}
{
// too long with pid
char longest_name[JVM_MAXPATHLEN];
memset(longest_name, 'a', JVM_MAXPATHLEN);
longest_name[JVM_MAXPATHLEN - 3] = '%';
longest_name[JVM_MAXPATHLEN - 2] = 'p';
longest_name[JVM_MAXPATHLEN - 1] = '\0';
o_result = make_log_name_internal((const char*)&longest_name, NULL, pid, tms);
assert(o_result == NULL, err_msg("Too long file name after pid expansion should return NULL, but got '%s'", o_result));
}
} }
#endif // PRODUCT #endif // PRODUCT
...@@ -640,9 +685,16 @@ gcLogFileStream::gcLogFileStream(const char* file_name) { ...@@ -640,9 +685,16 @@ gcLogFileStream::gcLogFileStream(const char* file_name) {
_bytes_written = 0L; _bytes_written = 0L;
_file_name = make_log_name(file_name, NULL); _file_name = make_log_name(file_name, NULL);
if (_file_name == NULL) {
warning("Cannot open file %s: file name is too long.\n", file_name);
_need_close = false;
UseGCLogFileRotation = false;
return;
}
// gc log file rotation // gc log file rotation
if (UseGCLogFileRotation && NumberOfGCLogFiles > 1) { if (UseGCLogFileRotation && NumberOfGCLogFiles > 1) {
char tempbuf[FILENAMEBUFLEN]; char tempbuf[JVM_MAXPATHLEN];
jio_snprintf(tempbuf, sizeof(tempbuf), "%s.%d" CURRENTAPPX, _file_name, _cur_file_num); jio_snprintf(tempbuf, sizeof(tempbuf), "%s.%d" CURRENTAPPX, _file_name, _cur_file_num);
_file = fopen(tempbuf, "w"); _file = fopen(tempbuf, "w");
} else { } else {
...@@ -674,10 +726,10 @@ void gcLogFileStream::write(const char* s, size_t len) { ...@@ -674,10 +726,10 @@ void gcLogFileStream::write(const char* s, size_t len) {
// concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log // concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log
// must be synchronized. // must be synchronized.
void gcLogFileStream::rotate_log(bool force, outputStream* out) { void gcLogFileStream::rotate_log(bool force, outputStream* out) {
char time_msg[FILENAMEBUFLEN]; char time_msg[O_BUFLEN];
char time_str[EXTRACHARLEN]; char time_str[EXTRACHARLEN];
char current_file_name[FILENAMEBUFLEN]; char current_file_name[JVM_MAXPATHLEN];
char renamed_file_name[FILENAMEBUFLEN]; char renamed_file_name[JVM_MAXPATHLEN];
if (!should_rotate(force)) { if (!should_rotate(force)) {
return; return;
...@@ -716,12 +768,15 @@ void gcLogFileStream::rotate_log(bool force, outputStream* out) { ...@@ -716,12 +768,15 @@ void gcLogFileStream::rotate_log(bool force, outputStream* out) {
// have a form of extended_filename.<i>.current where i is the current rotation // have a form of extended_filename.<i>.current where i is the current rotation
// file number. After it reaches max file size, the file will be saved and renamed // file number. After it reaches max file size, the file will be saved and renamed
// with .current removed from its tail. // with .current removed from its tail.
size_t filename_len = strlen(_file_name);
if (_file != NULL) { if (_file != NULL) {
jio_snprintf(renamed_file_name, filename_len + EXTRACHARLEN, "%s.%d", jio_snprintf(renamed_file_name, JVM_MAXPATHLEN, "%s.%d",
_file_name, _cur_file_num);
jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX,
_file_name, _cur_file_num); _file_name, _cur_file_num);
int result = jio_snprintf(current_file_name, JVM_MAXPATHLEN,
"%s.%d" CURRENTAPPX, _file_name, _cur_file_num);
if (result >= JVM_MAXPATHLEN) {
warning("Cannot create new log file name: %s: file name is too long.\n", current_file_name);
return;
}
const char* msg = force ? "GC log rotation request has been received." const char* msg = force ? "GC log rotation request has been received."
: "GC log file has reached the maximum size."; : "GC log file has reached the maximum size.";
...@@ -760,19 +815,23 @@ void gcLogFileStream::rotate_log(bool force, outputStream* out) { ...@@ -760,19 +815,23 @@ void gcLogFileStream::rotate_log(bool force, outputStream* out) {
_cur_file_num++; _cur_file_num++;
if (_cur_file_num > NumberOfGCLogFiles - 1) _cur_file_num = 0; if (_cur_file_num > NumberOfGCLogFiles - 1) _cur_file_num = 0;
jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX, int result = jio_snprintf(current_file_name, JVM_MAXPATHLEN, "%s.%d" CURRENTAPPX,
_file_name, _cur_file_num); _file_name, _cur_file_num);
if (result >= JVM_MAXPATHLEN) {
warning("Cannot create new log file name: %s: file name is too long.\n", current_file_name);
return;
}
_file = fopen(current_file_name, "w"); _file = fopen(current_file_name, "w");
if (_file != NULL) { if (_file != NULL) {
_bytes_written = 0L; _bytes_written = 0L;
_need_close = true; _need_close = true;
// reuse current_file_name for time_msg // reuse current_file_name for time_msg
jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, jio_snprintf(current_file_name, JVM_MAXPATHLEN,
"%s.%d", _file_name, _cur_file_num); "%s.%d", _file_name, _cur_file_num);
jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file created %s\n", jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file created %s\n",
os::local_time_string((char *)time_str, sizeof(time_str)), os::local_time_string((char *)time_str, sizeof(time_str)), current_file_name);
current_file_name);
write(time_msg, strlen(time_msg)); write(time_msg, strlen(time_msg));
if (out != NULL) { if (out != NULL) {
...@@ -820,32 +879,64 @@ bool defaultStream::has_log_file() { ...@@ -820,32 +879,64 @@ bool defaultStream::has_log_file() {
return _log_file != NULL; return _log_file != NULL;
} }
void defaultStream::init_log() { fileStream* defaultStream::open_file(const char* log_name) {
// %%% Need a MutexLocker?
const char* log_name = LogFile != NULL ? LogFile : "hotspot_%p.log";
const char* try_name = make_log_name(log_name, NULL); const char* try_name = make_log_name(log_name, NULL);
fileStream* file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name); if (try_name == NULL) {
if (!file->is_open()) { warning("Cannot open file %s: file name is too long.\n", log_name);
// Try again to open the file. return NULL;
char warnbuf[O_BUFLEN*2];
jio_snprintf(warnbuf, sizeof(warnbuf),
"Warning: Cannot open log file: %s\n", try_name);
// Note: This feature is for maintainer use only. No need for L10N.
jio_print(warnbuf);
FREE_C_HEAP_ARRAY(char, try_name, mtInternal);
try_name = make_log_name(log_name, os::get_temp_directory());
jio_snprintf(warnbuf, sizeof(warnbuf),
"Warning: Forcing option -XX:LogFile=%s\n", try_name);
jio_print(warnbuf);
delete file;
file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
} }
fileStream* file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
FREE_C_HEAP_ARRAY(char, try_name, mtInternal); FREE_C_HEAP_ARRAY(char, try_name, mtInternal);
if (file->is_open()) {
return file;
}
// Try again to open the file in the temp directory.
delete file;
char warnbuf[O_BUFLEN*2];
jio_snprintf(warnbuf, sizeof(warnbuf), "Warning: Cannot open log file: %s\n", log_name);
// Note: This feature is for maintainer use only. No need for L10N.
jio_print(warnbuf);
try_name = make_log_name(log_name, os::get_temp_directory());
if (try_name == NULL) {
warning("Cannot open file %s: file name is too long for directory %s.\n", log_name, os::get_temp_directory());
return NULL;
}
jio_snprintf(warnbuf, sizeof(warnbuf),
"Warning: Forcing option -XX:LogFile=%s\n", try_name);
jio_print(warnbuf);
file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
FREE_C_HEAP_ARRAY(char, try_name, mtInternal);
if (file->is_open()) { if (file->is_open()) {
return file;
}
delete file;
return NULL;
}
void defaultStream::init_log() {
// %%% Need a MutexLocker?
const char* log_name = LogFile != NULL ? LogFile : "hotspot_%p.log";
fileStream* file = open_file(log_name);
if (file != NULL) {
_log_file = file; _log_file = file;
xmlStream* xs = new(ResourceObj::C_HEAP, mtInternal) xmlStream(file); _outer_xmlStream = new(ResourceObj::C_HEAP, mtInternal) xmlStream(file);
_outer_xmlStream = xs; start_log();
} else {
// and leave xtty as NULL
LogVMOutput = false;
DisplayVMOutput = true;
LogCompilation = false;
}
}
void defaultStream::start_log() {
xmlStream*xs = _outer_xmlStream;
if (this == tty) xtty = xs; if (this == tty) xtty = xs;
// Write XML header. // Write XML header.
xs->print_cr("<?xml version='1.0' encoding='UTF-8'?>"); xs->print_cr("<?xml version='1.0' encoding='UTF-8'?>");
...@@ -900,13 +991,6 @@ void defaultStream::init_log() { ...@@ -900,13 +991,6 @@ void defaultStream::init_log() {
xs->head("tty"); xs->head("tty");
// All further non-markup text gets copied to the tty: // All further non-markup text gets copied to the tty:
xs->_text = this; // requires friend declaration! xs->_text = this; // requires friend declaration!
} else {
delete(file);
// and leave xtty as NULL
LogVMOutput = false;
DisplayVMOutput = true;
LogCompilation = false;
}
} }
// finish_log() is called during normal VM shutdown. finish_log_on_error() is // finish_log() is called during normal VM shutdown. finish_log_on_error() is
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册