--- old/src/share/vm/logging/logStream.cpp 2017-06-21 17:45:59.011284600 +0200 +++ new/src/share/vm/logging/logStream.cpp 2017-06-21 17:45:58.112609800 +0200 @@ -41,7 +41,7 @@ void LogStream::LineBuffer::ensure_cap(size_t atleast) { assert(_cap >= sizeof(_smallbuf), "sanity"); - if (_cap < atleast) { + if (_cap < atleast) { const size_t newcap = MAX2(_cap * 2, atleast * 2); char* const newbuf = (char*) os::malloc(newcap, mtLogging); if (_pos > 0) { // preserve old content @@ -58,20 +58,20 @@ void LogStream::LineBuffer::append(const char* s, size_t len) { assert(_buf[_pos] == '\0', "sanity"); - const size_t remaining = _cap - _pos; - ensure_cap(remaining + len + 1); + ensure_cap(_pos + len + 1); + assert(_cap >= _pos + len + 1, "sanity"); memcpy(_buf + _pos, s, len); _pos += len; _buf[_pos] = '\0'; } - + void LogStream::LineBuffer::reset() { _pos = 0; _buf[_pos] = '\0'; } void LogStream::write(const char* s, size_t len) { - + if (len > 0 && s[len - 1] == '\n') { _current_line.append(s, len - 1); // omit the newline. _log_handle.print("%s", _current_line.ptr()); --- old/src/share/vm/logging/logStream.hpp 2017-06-21 17:46:05.206783000 +0200 +++ new/src/share/vm/logging/logStream.hpp 2017-06-21 17:46:04.525735300 +0200 @@ -32,6 +32,7 @@ class LogStream : public outputStream { + friend class LogStreamTest_TestLineBufferAllocation_test_vm_Test; // see test/native/logging/test_logStream.cpp // Helper class, maintains the line buffer. For small line lengths, // we avoid malloc and use a fixed sized member char array. If LogStream @@ -49,14 +50,14 @@ const char* ptr() const { return _buf; } void append(const char* s, size_t len); void reset(); - }; + }; LineBuffer _current_line; LogTargetHandle _log_handle; // Prevent operator new for LogStream. static void* operator new (size_t); static void* operator new[] (size_t); - + public: // Constructor to support creation from a LogTarget instance. // --- old/test/native/logging/test_logStream.cpp 2017-06-21 17:46:10.583527700 +0200 +++ new/test/native/logging/test_logStream.cpp 2017-06-21 17:46:09.857743600 +0200 @@ -66,3 +66,25 @@ LogStream ls(Log(gc)::debug()); verify_stream(&ls); } + +TEST_VM_F(LogStreamTest, TestLineBufferAllocation) { + const int max_line_len = 1024; + char* const test_string = (char*) os::malloc(max_line_len, mtLogging); + memset(test_string, 'A', max_line_len); + for (int interval = 1; interval < max_line_len; interval++) { + LogStream ls(Log(logging)::info()); + int written = 0; + while (written < max_line_len) { + const int to_write = MIN2(interval, max_line_len - written); + ls.write(test_string, interval); + written += interval; + const char* const line_buffer = ls._current_line.ptr(); + for (int i = 0; i < written; i++) { + ASSERT_TRUE(line_buffer[i] == 'A'); + } + ASSERT_TRUE(line_buffer[written] == '\0'); + } + ls.cr(); // I do not expect printout, nor do I care. Just call cr() to flush and avoid assert in ~LogStream(). + } +} +