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

Merge

......@@ -501,6 +501,8 @@ f09d1f6a401e25a54dad44bb7bea482e47558af5 jdk8u20-b23
00cf2b6f51b9560b01030e8f4c28c466f0b21fe3 hs25.20-b23
19408d5fd31c25ce60c43dd33e92b96e8df4a4ea jdk8u20-b25
eaa4074a7e3975cd33ec55e6b584586e2ac681bd jdk8u20-b26
7c9925f21c2529a88eb64b8039cc080f60b85e01 jdk8u20-b31
7edb04063a423e278fe34a0006d25fee198f495e jdk8u20-b32
4828415ebbf11e205dcc08e97ad5ae7dd03522f9 jdk8u40-b00
d952af8cf67dd1e7ab5fec9a299c6c6dafd1863e hs25.40-b01
f0afba33c928ddaa2d5f003b90d683c143f78ea3 hs25.40-b02
......@@ -544,6 +546,13 @@ e62c06b887310b5bd23be9b817a9a6f0daf0d0e1 jdk8u25-b15
6467bdd4d22d8b140844dc847c43b9ba7cb0bbd1 jdk8u25-b16
28b50d07f6f8c5a567b6a25e95a423948114a004 jdk8u25-b17
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
f10fe402dfb1543723b4b117a7cba3ea3d4159f1 hs25.40-b15
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.
#
# This code is free software; you can redistribute it and/or modify it
......@@ -31,7 +31,7 @@
#
# Don't put quotes (fail windows build).
HOTSPOT_VM_COPYRIGHT=Copyright 2014
HOTSPOT_VM_COPYRIGHT=Copyright 2015
HS_MAJOR_VER=25
HS_MINOR_VER=40
......
......@@ -89,8 +89,8 @@ class BCEscapeAnalyzer::StateInfo {
public:
ArgumentMap *_vars;
ArgumentMap *_stack;
short _stack_height;
short _max_stack;
int _stack_height;
int _max_stack;
bool _initialized;
ArgumentMap empty_map;
......
......@@ -1908,11 +1908,12 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
InstanceKlass::cast(WK_KLASS(Reference_klass))->set_reference_type(REF_OTHER);
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(WeakReference_klass))->set_reference_type(REF_WEAK);
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(Cleaner_klass))->set_reference_type(REF_CLEANER);
// JSR 292 classes
WKID jsr292_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
......
......@@ -128,6 +128,7 @@ class Ticks;
do_klass(WeakReference_klass, java_lang_ref_WeakReference, Pre ) \
do_klass(FinalReference_klass, java_lang_ref_FinalReference, 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(Thread_klass, java_lang_Thread, Pre ) \
......
......@@ -1553,14 +1553,14 @@ void ClassVerifier::verify_method(methodHandle m, TRAPS) {
case Bytecodes::_invokespecial :
case Bytecodes::_invokestatic :
verify_invoke_instructions(
&bcs, code_length, &current_frame,
&this_uninit, return_type, cp, CHECK_VERIFY(this));
&bcs, code_length, &current_frame, (bci >= ex_min && bci < ex_max),
&this_uninit, return_type, cp, &stackmap_table, CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_invokeinterface :
case Bytecodes::_invokedynamic :
verify_invoke_instructions(
&bcs, code_length, &current_frame,
&this_uninit, return_type, cp, CHECK_VERIFY(this));
&bcs, code_length, &current_frame, (bci >= ex_min && bci < ex_max),
&this_uninit, return_type, cp, &stackmap_table, CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_new :
{
......@@ -2408,8 +2408,9 @@ bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) {
void ClassVerifier::verify_invoke_init(
RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type,
StackMapFrame* current_frame, u4 code_length, bool *this_uninit,
constantPoolHandle cp, TRAPS) {
StackMapFrame* current_frame, u4 code_length, bool in_try_block,
bool *this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table,
TRAPS) {
u2 bci = bcs->bci();
VerificationType type = current_frame->pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this));
......@@ -2425,9 +2426,10 @@ void ClassVerifier::verify_invoke_init(
return;
}
// Check if this call is done from inside of a TRY block. If so, make
// sure that all catch clause paths end in a throw. Otherwise, this
// can result in returning an incomplete object.
// 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 can
// result in returning an incomplete object.
if (in_try_block) {
ExceptionTable exhandlers(_method());
int exlength = exhandlers.length();
for(int i = 0; i < exlength; i++) {
......@@ -2448,6 +2450,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).
verify_exception_handler_targets(bci, true, current_frame,
stackmap_table, CHECK_VERIFY(this));
} // in_try_block
current_frame->initialize_object(type, current_type());
*this_uninit = true;
} else if (type.is_uninitialized()) {
......@@ -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);
} else {
verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx()),
......@@ -2528,8 +2544,8 @@ bool ClassVerifier::is_same_or_direct_interface(
void ClassVerifier::verify_invoke_instructions(
RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
bool *this_uninit, VerificationType return_type,
constantPoolHandle cp, TRAPS) {
bool in_try_block, bool *this_uninit, VerificationType return_type,
constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS) {
// Make sure the constant pool item is the right type
u2 index = bcs->get_index_u2();
Bytecodes::Code opcode = bcs->raw_code();
......@@ -2699,7 +2715,8 @@ void ClassVerifier::verify_invoke_instructions(
opcode != Bytecodes::_invokedynamic) {
if (method_name == vmSymbols::object_initializer_name()) { // <init> method
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
// Ensures that target class is assignable to method class.
if (opcode == Bytecodes::_invokespecial) {
......
......@@ -301,8 +301,9 @@ class ClassVerifier : public StackObj {
void verify_invoke_init(
RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type,
StackMapFrame* current_frame, u4 code_length, bool* this_uninit,
constantPoolHandle cp, TRAPS);
StackMapFrame* current_frame, u4 code_length, bool in_try_block,
bool* this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table,
TRAPS);
// 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.
......@@ -316,8 +317,8 @@ class ClassVerifier : public StackObj {
void verify_invoke_instructions(
RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
bool* this_uninit, VerificationType return_type,
constantPoolHandle cp, TRAPS);
bool in_try_block, bool* this_uninit, VerificationType return_type,
constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS);
VerificationType get_newarray_type(u2 index, u2 bci, TRAPS);
void verify_anewarray(u2 bci, u2 index, constantPoolHandle cp,
......
......@@ -79,6 +79,7 @@
template(java_lang_ref_WeakReference, "java/lang/ref/WeakReference") \
template(java_lang_ref_FinalReference, "java/lang/ref/FinalReference") \
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_reflect_AccessibleObject, "java/lang/reflect/AccessibleObject") \
template(java_lang_reflect_Method, "java/lang/reflect/Method") \
......
......@@ -738,7 +738,7 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen,
// Support for parallelizing survivor space rescan
if ((CMSParallelRemarkEnabled && CMSParallelSurvivorRemarkEnabled) || CMSParallelInitialMarkEnabled) {
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_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, 2*max_plab_samples, mtGC);
......@@ -796,6 +796,12 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen,
_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 {
return "concurrent mark-sweep generation";
}
......
......@@ -764,6 +764,10 @@ class CMSCollector: public CHeapObj<mtGC> {
size_t* _cursor;
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
bool take_from_overflow_list(size_t num, CMSMarkStack* to_stack);
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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -47,6 +47,13 @@ public:
// active field set to true.
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
// buffer empty. If a closure application returns "false", return
// "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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -31,11 +31,15 @@
#include "runtime/thread.inline.hpp"
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)
{}
void PtrQueue::flush() {
PtrQueue::~PtrQueue() {
assert(_perm || (_buf == NULL), "queue must be flushed before delete");
}
void PtrQueue::flush_impl() {
if (!_perm && _buf != NULL) {
if (_index == _sz) {
// 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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -65,15 +65,18 @@ protected:
Mutex* _lock;
PtrQueueSet* qset() { return _qset; }
bool is_permanent() const { return _perm; }
// Process queue entries and release resources, if not permanent.
void flush_impl();
public:
// Initialize this queue to contain a null buffer, and be part of the
// given PtrQueueSet.
PtrQueue(PtrQueueSet* qset, bool perm = false, bool active = false);
// Release any contained resources.
virtual void flush();
// Calls flush() when destroyed.
~PtrQueue() { flush(); }
// Requires queue flushed or permanent.
~PtrQueue();
// Associate a lock with a ptr queue.
void set_lock(Mutex* lock) { _lock = lock; }
......
......@@ -39,7 +39,7 @@ void ObjPtrQueue::flush() {
// first before we flush it, otherwise we might end up with an
// enqueued buffer with refs into the CSet which breaks our invariants.
filter();
PtrQueue::flush();
flush_impl();
}
// 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.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -60,9 +60,8 @@ public:
// field to true. This is done in JavaThread::initialize_queues().
PtrQueue(qset, perm, false /* active */) { }
// Overrides PtrQueue::flush() so that it can filter the buffer
// before it is flushed.
virtual void flush();
// Process queue entries and free resources.
void flush();
// Overrides PtrQueue::should_enqueue_buffer(). See the method's
// definition for more information.
......
......@@ -63,7 +63,8 @@ public:
virtual ~ParGCAllocBuffer() {}
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() {
......
......@@ -118,6 +118,7 @@ ReferenceProcessor::ReferenceProcessor(MemRegion span,
_discoveredWeakRefs = &_discoveredSoftRefs[_max_num_q];
_discoveredFinalRefs = &_discoveredWeakRefs[_max_num_q];
_discoveredPhantomRefs = &_discoveredFinalRefs[_max_num_q];
_discoveredCleanerRefs = &_discoveredPhantomRefs[_max_num_q];
// Initialize all entries to NULL
for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) {
......@@ -246,6 +247,13 @@ ReferenceProcessorStats ReferenceProcessor::process_discovered_references(
phantom_count =
process_discovered_reflist(_discoveredPhantomRefs, NULL, false,
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
......@@ -883,6 +891,7 @@ void ReferenceProcessor::balance_all_queues() {
balance_queues(_discoveredWeakRefs);
balance_queues(_discoveredFinalRefs);
balance_queues(_discoveredPhantomRefs);
balance_queues(_discoveredCleanerRefs);
}
size_t
......@@ -1042,6 +1051,9 @@ inline DiscoveredList* ReferenceProcessor::get_discovered_list(ReferenceType rt)
case REF_PHANTOM:
list = &_discoveredPhantomRefs[id];
break;
case REF_CLEANER:
list = &_discoveredCleanerRefs[id];
break;
case REF_NONE:
// we should not reach here if we are an InstanceRefKlass
default:
......@@ -1307,6 +1319,17 @@ void ReferenceProcessor::preclean_discovered_references(
preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive,
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) {
case 1: return "WeakRef";
case 2: return "FinalRef";
case 3: return "PhantomRef";
case 4: return "CleanerRef";
}
ShouldNotReachHere();
return NULL;
......
......@@ -264,9 +264,10 @@ class ReferenceProcessor : public CHeapObj<mtGC> {
DiscoveredList* _discoveredWeakRefs;
DiscoveredList* _discoveredFinalRefs;
DiscoveredList* _discoveredPhantomRefs;
DiscoveredList* _discoveredCleanerRefs;
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 max_num_q() { return _max_num_q; }
......
......@@ -35,7 +35,8 @@ enum ReferenceType {
REF_SOFT, // Subclass of java/lang/ref/SoftReference
REF_WEAK, // Subclass of java/lang/ref/WeakReference
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
......@@ -235,22 +235,19 @@ void ThreadLocalAllocBuffer::startup_initialization() {
}
size_t ThreadLocalAllocBuffer::initial_desired_size() {
size_t init_sz;
size_t init_sz = 0;
if (TLABSize > 0) {
init_sz = MIN2(TLABSize / HeapWordSize, max_size());
} else if (global_stats() == NULL) {
// Startup issue - main thread initialized before heap initialized.
init_sz = min_size();
} else {
init_sz = TLABSize / HeapWordSize;
} else if (global_stats() != NULL) {
// Initial size is a function of the average number of allocating threads.
unsigned nof_threads = global_stats()->allocating_threads_avg();
init_sz = (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize) /
(nof_threads * target_refills());
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;
}
......
......@@ -105,7 +105,7 @@ public:
// 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 void set_max_size(size_t max_size) { _max_size = max_size; }
......
......@@ -671,6 +671,7 @@ typedef BinaryTreeDictionary<Metablock, FreeList<Metablock> > MetablockTreeDicti
static_field(SystemDictionary, WK_KLASS(WeakReference_klass), Klass*) \
static_field(SystemDictionary, WK_KLASS(FinalReference_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(Thread_klass), Klass*) \
static_field(SystemDictionary, WK_KLASS(ThreadGroup_klass), Klass*) \
......
......@@ -41,6 +41,8 @@ class defaultStream : public xmlTextStream {
void init();
void init_log();
fileStream* open_file(const char* log_name);
void start_log();
void finish_log();
void finish_log_on_error(char *buf, int buflen);
public:
......
......@@ -370,7 +370,6 @@ extern Mutex* tty_lock;
#define EXTRACHARLEN 32
#define CURRENTAPPX ".current"
#define FILENAMEBUFLEN 1024
// convert YYYY-MM-DD HH:MM:SS to YYYY-MM-DD_HH-MM-SS
char* get_datetime_string(char *buf, size_t 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
buffer_length = strlen(log_name) + 1;
}
// const char* star = strchr(basename, '*');
const char* pts = strstr(basename, "%p");
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
buffer_length += strlen(tms);
}
// File name is too long.
if (buffer_length > JVM_MAXPATHLEN) {
return NULL;
}
// Create big enough buffer.
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
void test_loggc_filename() {
int pid;
char tms[32];
char i_result[FILENAMEBUFLEN];
char i_result[JVM_MAXPATHLEN];
const char* o_result;
get_datetime_string(tms, sizeof(tms));
pid = os::current_process_id();
// 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);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test.log\", NULL)");
FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
// 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);
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);
// 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);
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);
// %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);
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);
// %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);
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);
// %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);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%t.log\", NULL)");
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
......@@ -640,9 +685,16 @@ gcLogFileStream::gcLogFileStream(const char* file_name) {
_bytes_written = 0L;
_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
if (UseGCLogFileRotation && NumberOfGCLogFiles > 1) {
char tempbuf[FILENAMEBUFLEN];
char tempbuf[JVM_MAXPATHLEN];
jio_snprintf(tempbuf, sizeof(tempbuf), "%s.%d" CURRENTAPPX, _file_name, _cur_file_num);
_file = fopen(tempbuf, "w");
} else {
......@@ -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
// must be synchronized.
void gcLogFileStream::rotate_log(bool force, outputStream* out) {
char time_msg[FILENAMEBUFLEN];
char time_msg[O_BUFLEN];
char time_str[EXTRACHARLEN];
char current_file_name[FILENAMEBUFLEN];
char renamed_file_name[FILENAMEBUFLEN];
char current_file_name[JVM_MAXPATHLEN];
char renamed_file_name[JVM_MAXPATHLEN];
if (!should_rotate(force)) {
return;
......@@ -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
// file number. After it reaches max file size, the file will be saved and renamed
// with .current removed from its tail.
size_t filename_len = strlen(_file_name);
if (_file != NULL) {
jio_snprintf(renamed_file_name, filename_len + EXTRACHARLEN, "%s.%d",
_file_name, _cur_file_num);
jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX,
jio_snprintf(renamed_file_name, JVM_MAXPATHLEN, "%s.%d",
_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."
: "GC log file has reached the maximum size.";
......@@ -760,19 +815,23 @@ void gcLogFileStream::rotate_log(bool force, outputStream* out) {
_cur_file_num++;
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);
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");
if (_file != NULL) {
_bytes_written = 0L;
_need_close = true;
// 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);
jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file created %s\n",
os::local_time_string((char *)time_str, sizeof(time_str)),
current_file_name);
os::local_time_string((char *)time_str, sizeof(time_str)), current_file_name);
write(time_msg, strlen(time_msg));
if (out != NULL) {
......@@ -820,32 +879,64 @@ bool defaultStream::has_log_file() {
return _log_file != NULL;
}
void defaultStream::init_log() {
// %%% Need a MutexLocker?
const char* log_name = LogFile != NULL ? LogFile : "hotspot_%p.log";
fileStream* defaultStream::open_file(const char* log_name) {
const char* try_name = make_log_name(log_name, NULL);
if (try_name == NULL) {
warning("Cannot open file %s: file name is too long.\n", log_name);
return NULL;
}
fileStream* file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
if (!file->is_open()) {
// Try again to open the file.
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", try_name);
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);
FREE_C_HEAP_ARRAY(char, try_name, mtInternal);
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);
delete file;
file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
}
FREE_C_HEAP_ARRAY(char, try_name, mtInternal);
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;
xmlStream* xs = new(ResourceObj::C_HEAP, mtInternal) xmlStream(file);
_outer_xmlStream = xs;
_outer_xmlStream = new(ResourceObj::C_HEAP, mtInternal) xmlStream(file);
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;
// Write XML header.
xs->print_cr("<?xml version='1.0' encoding='UTF-8'?>");
......@@ -900,13 +991,6 @@ void defaultStream::init_log() {
xs->head("tty");
// All further non-markup text gets copied to the tty:
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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册