changeset 13365:ff28370e679e

8181917: Refactor UL LogStreams to avoid using resource area Reviewed-by: ehelin, mlarsson
author stuefe
date Fri, 21 Jul 2017 09:50:12 +0200
parents 81043dceedeb
children a3b8c747b6bf
files src/cpu/sparc/vm/vm_version_sparc.cpp src/cpu/x86/vm/vm_version_x86.cpp src/share/vm/classfile/classFileParser.cpp src/share/vm/classfile/classLoader.cpp src/share/vm/classfile/classLoaderData.cpp src/share/vm/classfile/classLoaderData.hpp src/share/vm/classfile/defaultMethods.cpp src/share/vm/classfile/dictionary.cpp src/share/vm/classfile/loaderConstraints.cpp src/share/vm/classfile/modules.cpp src/share/vm/classfile/protectionDomainCache.cpp src/share/vm/classfile/sharedPathsMiscInfo.cpp src/share/vm/classfile/sharedPathsMiscInfo.hpp src/share/vm/classfile/systemDictionary.cpp src/share/vm/classfile/verifier.cpp src/share/vm/code/nmethod.cpp src/share/vm/compiler/compileBroker.cpp src/share/vm/compiler/compileTask.cpp src/share/vm/compiler/compileTask.hpp src/share/vm/gc/cms/compactibleFreeListSpace.cpp src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp src/share/vm/gc/cms/parNewGeneration.cpp src/share/vm/gc/cms/parOopClosures.inline.hpp src/share/vm/gc/g1/g1AllocRegion.cpp src/share/vm/gc/g1/g1CollectedHeap.cpp src/share/vm/gc/g1/g1GCPhaseTimes.cpp src/share/vm/gc/g1/g1HeapVerifier.cpp src/share/vm/gc/g1/g1RemSet.cpp src/share/vm/gc/g1/heapRegion.cpp src/share/vm/gc/parallel/adjoiningGenerations.cpp src/share/vm/gc/parallel/gcTaskManager.cpp src/share/vm/gc/parallel/psParallelCompact.cpp src/share/vm/gc/parallel/psPromotionManager.cpp src/share/vm/gc/shared/collectedHeap.cpp src/share/vm/gc/shared/gcTraceTime.inline.hpp src/share/vm/interpreter/linkResolver.cpp src/share/vm/logging/log.hpp src/share/vm/logging/logHandle.hpp src/share/vm/logging/logStream.cpp src/share/vm/logging/logStream.hpp src/share/vm/logging/logStream.inline.hpp src/share/vm/memory/binaryTreeDictionary.cpp src/share/vm/memory/filemap.cpp src/share/vm/memory/metaspace.cpp src/share/vm/memory/universe.cpp src/share/vm/oops/generateOopMap.cpp src/share/vm/oops/instanceKlass.cpp src/share/vm/oops/klassVtable.cpp src/share/vm/opto/runtime.cpp src/share/vm/prims/jvmtiExport.cpp src/share/vm/prims/jvmtiImpl.cpp src/share/vm/prims/stackwalk.cpp src/share/vm/runtime/arguments.cpp src/share/vm/runtime/java.cpp src/share/vm/runtime/os.cpp src/share/vm/runtime/safepoint.cpp src/share/vm/runtime/sweeper.cpp src/share/vm/runtime/thread.cpp src/share/vm/runtime/vm_operations.cpp src/share/vm/runtime/vm_version.cpp src/share/vm/utilities/exceptions.cpp test/native/logging/test_logConfiguration.cpp test/native/logging/test_logStream.cpp
diffstat 63 files changed, 662 insertions(+), 508 deletions(-) [+]
line wrap: on
line diff
--- a/src/cpu/sparc/vm/vm_version_sparc.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/cpu/sparc/vm/vm_version_sparc.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "asm/macroAssembler.inline.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/resourceArea.hpp"
 #include "prims/jvm.h"
 #include "runtime/java.hpp"
@@ -426,7 +427,8 @@
 
   if (log_is_enabled(Info, os, cpu)) {
     ResourceMark rm;
-    outputStream* log = Log(os, cpu)::info_stream();
+    LogStream ls(Log(os, cpu)::info());
+    outputStream* log = &ls;
     log->print_cr("L1 data cache line size: %u", L1_data_cache_line_size());
     log->print_cr("L2 data cache line size: %u", L2_data_cache_line_size());
     log->print("Allocation");
--- a/src/cpu/x86/vm/vm_version_x86.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/cpu/x86/vm/vm_version_x86.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -26,6 +26,7 @@
 #include "asm/macroAssembler.hpp"
 #include "asm/macroAssembler.inline.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/resourceArea.hpp"
 #include "prims/jvm.h"
 #include "runtime/java.hpp"
@@ -1355,7 +1356,8 @@
 
 #ifndef PRODUCT
   if (log_is_enabled(Info, os, cpu)) {
-    outputStream* log = Log(os, cpu)::info_stream();
+    LogStream ls(Log(os, cpu)::info());
+    outputStream* log = &ls;
     log->print_cr("Logical CPUs per core: %u",
                   logical_processors_per_package());
     log->print_cr("L1 data cache line size: %u", L1_data_cache_line_size());
--- a/src/share/vm/classfile/classFileParser.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/classfile/classFileParser.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -38,6 +38,7 @@
 #include "classfile/vmSymbols.hpp"
 #include "gc/shared/gcLocker.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/allocation.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/oopFactory.hpp"
@@ -5910,14 +5911,15 @@
   assert(is_internal_format(_class_name), "external class name format used internally");
 
   if (!is_internal()) {
-    if (log_is_enabled(Debug, class, preorder)){
+    LogTarget(Debug, class, preorder) lt;
+    if (lt.is_enabled()){
       ResourceMark rm(THREAD);
-      outputStream* log = Log(class, preorder)::debug_stream();
-      log->print("%s", _class_name->as_klass_external_name());
+      LogStream ls(lt);
+      ls.print("%s", _class_name->as_klass_external_name());
       if (stream->source() != NULL) {
-        log->print(" source: %s", stream->source());
+        ls.print(" source: %s", stream->source());
       }
-      log->cr();
+      ls.cr();
     }
 
 #if INCLUDE_CDS
--- a/src/share/vm/classfile/classLoader.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/classfile/classLoader.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -40,6 +40,8 @@
 #include "gc/shared/generation.hpp"
 #include "interpreter/bytecodeStream.hpp"
 #include "interpreter/oopMapCache.hpp"
+#include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "logging/logTag.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/filemap.hpp"
@@ -609,25 +611,25 @@
 }
 
 void ClassLoader::trace_class_path(const char* msg, const char* name) {
-  if (log_is_enabled(Info, class, path)) {
-    ResourceMark rm;
-    outputStream* out = Log(class, path)::info_stream();
+  LogTarget(Info, class, path) lt;
+  if (lt.is_enabled()) {
+    LogStream ls(lt);
     if (msg) {
-      out->print("%s", msg);
+      ls.print("%s", msg);
     }
     if (name) {
       if (strlen(name) < 256) {
-        out->print("%s", name);
+        ls.print("%s", name);
       } else {
         // For very long paths, we need to print each character separately,
         // as print_cr() has a length limit
         while (name[0] != '\0') {
-          out->print("%c", name[0]);
+          ls.print("%c", name[0]);
           name++;
         }
       }
     }
-    out->cr();
+    ls.cr();
   }
 }
 
--- a/src/share/vm/classfile/classLoaderData.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/classfile/classLoaderData.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -57,6 +57,7 @@
 #include "code/codeCache.hpp"
 #include "gc/shared/gcLocker.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/metaspaceShared.hpp"
 #include "memory/oopFactory.hpp"
@@ -476,16 +477,17 @@
   // Tell serviceability tools these classes are unloading
   classes_do(InstanceKlass::notify_unload_class);
 
-  if (log_is_enabled(Debug, class, loader, data)) {
+  LogTarget(Debug, class, loader, data) lt;
+  if (lt.is_enabled()) {
     ResourceMark rm;
-    outputStream* log = Log(class, loader, data)::debug_stream();
-    log->print(": unload loader data " INTPTR_FORMAT, p2i(this));
-    log->print(" for instance " INTPTR_FORMAT " of %s", p2i((void *)class_loader()),
+    LogStream ls(lt);
+    ls.print(": unload loader data " INTPTR_FORMAT, p2i(this));
+    ls.print(" for instance " INTPTR_FORMAT " of %s", p2i((void *)class_loader()),
                loader_name());
     if (is_anonymous()) {
-      log->print(" for anonymous class  " INTPTR_FORMAT " ", p2i(_klasses));
+      ls.print(" for anonymous class  " INTPTR_FORMAT " ", p2i(_klasses));
     }
-    log->cr();
+    ls.cr();
   }
 
   // In some rare cases items added to this list will not be freed elsewhere.
@@ -803,9 +805,11 @@
     cld->set_next(next);
     ClassLoaderData* exchanged = (ClassLoaderData*)Atomic::cmpxchg_ptr(cld, list_head, next);
     if (exchanged == next) {
-      if (log_is_enabled(Debug, class, loader, data)) {
+      LogTarget(Debug, class, loader, data) lt;
+      if (lt.is_enabled()) {
        PauseNoSafepointVerifier pnsv(&no_safepoints); // Need safe points for JavaCalls::call_virtual
-       log_creation(loader, cld, CHECK_NULL);
+       LogStream ls(lt);
+       print_creation(&ls, loader, cld, CHECK_NULL);
       }
       return cld;
     }
@@ -813,7 +817,7 @@
   } while (true);
 }
 
-void ClassLoaderDataGraph::log_creation(Handle loader, ClassLoaderData* cld, TRAPS) {
+void ClassLoaderDataGraph::print_creation(outputStream* out, Handle loader, ClassLoaderData* cld, TRAPS) {
   Handle string;
   if (loader.not_null()) {
     // Include the result of loader.toString() in the output. This allows
@@ -831,16 +835,15 @@
   }
 
   ResourceMark rm;
-  outputStream* log = Log(class, loader, data)::debug_stream();
-  log->print("create class loader data " INTPTR_FORMAT, p2i(cld));
-  log->print(" for instance " INTPTR_FORMAT " of %s", p2i((void *)cld->class_loader()),
+  out->print("create class loader data " INTPTR_FORMAT, p2i(cld));
+  out->print(" for instance " INTPTR_FORMAT " of %s", p2i((void *)cld->class_loader()),
              cld->loader_name());
 
   if (string.not_null()) {
-    log->print(": ");
-    java_lang_String::print(string(), log);
+    out->print(": ");
+    java_lang_String::print(string(), out);
   }
-  log->cr();
+  out->cr();
 }
 
 
@@ -981,12 +984,12 @@
   while (curr != _saved_head) {
     if (!curr->claimed()) {
       array->push(curr);
-
-      if (log_is_enabled(Debug, class, loader, data)) {
-        outputStream* log = Log(class, loader, data)::debug_stream();
-        log->print("found new CLD: ");
-        curr->print_value_on(log);
-        log->cr();
+      LogTarget(Debug, class, loader, data) lt;
+      if (lt.is_enabled()) {
+        LogStream ls(lt);
+        ls.print("found new CLD: ");
+        curr->print_value_on(&ls);
+        ls.cr();
       }
     }
 
--- a/src/share/vm/classfile/classLoaderData.hpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/classfile/classLoaderData.hpp	Fri Jul 21 09:50:12 2017 +0200
@@ -129,7 +129,7 @@
   static void dump_on(outputStream * const out) PRODUCT_RETURN;
   static void dump() { dump_on(tty); }
   static void verify();
-  static void log_creation(Handle loader, ClassLoaderData* cld, TRAPS);
+  static void print_creation(outputStream* out, Handle loader, ClassLoaderData* cld, TRAPS);
 
   static bool unload_list_contains(const void* x);
 #ifndef PRODUCT
--- a/src/share/vm/classfile/defaultMethods.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/classfile/defaultMethods.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -27,6 +27,7 @@
 #include "classfile/defaultMethods.hpp"
 #include "classfile/symbolTable.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/allocation.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/resourceArea.hpp"
@@ -433,11 +434,11 @@
     } else if (num_defaults > 1) {
       _exception_message = generate_conflicts_message(&qualified_methods,CHECK);
       _exception_name = vmSymbols::java_lang_IncompatibleClassChangeError();
-      if (log_is_enabled(Debug, defaultmethods)) {
-        ResourceMark rm;
-        outputStream* logstream = Log(defaultmethods)::debug_stream();
-        _exception_message->print_value_on(logstream);
-        logstream->cr();
+      LogTarget(Debug, defaultmethods) lt;
+      if (lt.is_enabled()) {
+        LogStream ls(lt);
+        _exception_message->print_value_on(&ls);
+        ls.cr();
       }
     }
   }
@@ -658,15 +659,16 @@
     super = super->java_super();
   }
 
-  if (log_is_enabled(Debug, defaultmethods)) {
-    log_debug(defaultmethods)("Slots that need filling:");
+  LogTarget(Debug, defaultmethods) lt;
+  if (lt.is_enabled()) {
+    lt.print("Slots that need filling:");
     ResourceMark rm;
-    outputStream* logstream = Log(defaultmethods)::debug_stream();
-    streamIndentor si(logstream);
+    LogStream ls(lt);
+    streamIndentor si(&ls);
     for (int i = 0; i < slots->length(); ++i) {
-      logstream->indent();
-      slots->at(i)->print_on(logstream);
-      logstream->cr();
+      ls.indent();
+      slots->at(i)->print_on(&ls);
+      ls.cr();
     }
   }
 
@@ -792,12 +794,14 @@
   KeepAliveVisitor loadKeepAlive(&keepAlive);
   loadKeepAlive.run(klass);
 
-  if (log_is_enabled(Debug, defaultmethods)) {
+  LogTarget(Debug, defaultmethods) lt;
+  if (lt.is_enabled()) {
     ResourceMark rm;
-    log_debug(defaultmethods)("%s %s requires default method processing",
-                              klass->is_interface() ? "Interface" : "Class",
-                              klass->name()->as_klass_external_name());
-    PrintHierarchy printer(Log(defaultmethods)::debug_stream());
+    lt.print("%s %s requires default method processing",
+             klass->is_interface() ? "Interface" : "Class",
+             klass->name()->as_klass_external_name());
+    LogStream ls(lt);
+    PrintHierarchy printer(&ls);
     printer.run(klass);
   }
 
@@ -806,12 +810,13 @@
 
   for (int i = 0; i < empty_slots->length(); ++i) {
     EmptyVtableSlot* slot = empty_slots->at(i);
-    if (log_is_enabled(Debug, defaultmethods)) {
-      outputStream* logstream = Log(defaultmethods)::debug_stream();
-      streamIndentor si(logstream, 2);
-      logstream->indent().print("Looking for default methods for slot ");
-      slot->print_on(logstream);
-      logstream->cr();
+    LogTarget(Debug, defaultmethods) lt;
+    if (lt.is_enabled()) {
+      LogStream ls(lt);
+      streamIndentor si(&ls, 2);
+      ls.indent().print("Looking for default methods for slot ");
+      slot->print_on(&ls);
+      ls.cr();
     }
     generate_erased_defaults(klass, empty_slots, slot, CHECK);
   }
@@ -911,16 +916,17 @@
       MethodFamily* method = slot->get_binding();
       BytecodeBuffer buffer;
 
-      if (log_is_enabled(Debug, defaultmethods)) {
+      LogTarget(Debug, defaultmethods) lt;
+      if (lt.is_enabled()) {
         ResourceMark rm(THREAD);
-        outputStream* logstream = Log(defaultmethods)::debug_stream();
-        logstream->print("for slot: ");
-        slot->print_on(logstream);
-        logstream->cr();
+        LogStream ls(lt);
+        ls.print("for slot: ");
+        slot->print_on(&ls);
+        ls.cr();
         if (method->has_target()) {
-          method->print_selected(logstream, 1);
+          method->print_selected(&ls, 1);
         } else if (method->throws_exception()) {
-          method->print_exception(logstream, 1);
+          method->print_exception(&ls, 1);
         }
       }
 
--- a/src/share/vm/classfile/dictionary.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/classfile/dictionary.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -29,6 +29,8 @@
 #include "classfile/protectionDomainCache.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/systemDictionaryShared.hpp"
+#include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/iterator.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
@@ -136,10 +138,10 @@
     //          via a store to _pd_set.
     OrderAccess::release_store_ptr(&_pd_set, new_head);
   }
-  if (log_is_enabled(Trace, protectiondomain)) {
-    ResourceMark rm;
-    outputStream* log = Log(protectiondomain)::trace_stream();
-    print_count(log);
+  LogTarget(Trace, protectiondomain) lt;
+  if (lt.is_enabled()) {
+    LogStream ls(lt);
+    print_count(&ls);
   }
 }
 
--- a/src/share/vm/classfile/loaderConstraints.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/classfile/loaderConstraints.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "classfile/classLoaderData.inline.hpp"
 #include "classfile/loaderConstraints.hpp"
+#include "logging/log.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/handles.inline.hpp"
@@ -88,6 +89,7 @@
 
 void LoaderConstraintTable::purge_loader_constraints() {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+  LogTarget(Info, class, loader, constraints) lt;
   // Remove unloaded entries from constraint table
   for (int index = 0; index < table_size(); index++) {
     LoaderConstraintEntry** p = bucket_addr(index);
@@ -98,14 +100,13 @@
       if (klass != NULL &&
           klass->class_loader_data()->is_unloading()) {
         probe->set_klass(NULL);
-        if (log_is_enabled(Info, class, loader, constraints)) {
+        if (lt.is_enabled()) {
           ResourceMark rm;
-          outputStream* out = Log(class, loader, constraints)::info_stream();
-          out->print_cr("purging class object from constraint for name %s,"
+          lt.print("purging class object from constraint for name %s,"
                      " loader list:",
                      probe->name()->as_C_string());
           for (int i = 0; i < probe->num_loaders(); i++) {
-            out->print_cr("    [%d]: %s", i,
+            lt.print("    [%d]: %s", i,
                           probe->loader_data(i)->loader_name());
           }
         }
@@ -114,10 +115,9 @@
       int n = 0;
       while (n < probe->num_loaders()) {
         if (probe->loader_data(n)->is_unloading()) {
-            if (log_is_enabled(Info, class, loader, constraints)) {
+            if (lt.is_enabled()) {
               ResourceMark rm;
-              outputStream* out = Log(class, loader, constraints)::info_stream();
-              out->print_cr("purging loader %s from constraint for name %s",
+              lt.print("purging loader %s from constraint for name %s",
                             probe->loader_data(n)->loader_name(),
                             probe->name()->as_C_string()
                             );
@@ -129,12 +129,11 @@
           probe->set_loader_data(n, probe->loader_data(num));
           probe->set_loader_data(num, NULL);
 
-            if (log_is_enabled(Info, class, loader, constraints)) {
+            if (lt.is_enabled()) {
               ResourceMark rm;
-              outputStream* out = Log(class, loader, constraints)::info_stream();
-              out->print_cr("new loader list:");
+              lt.print("new loader list:");
               for (int i = 0; i < probe->num_loaders(); i++) {
-                out->print_cr("    [%d]: %s", i,
+                lt.print("    [%d]: %s", i,
                               probe->loader_data(i)->loader_name());
               }
             }
@@ -146,10 +145,9 @@
       }
       // Check whether entry should be purged
       if (probe->num_loaders() < 2) {
-            if (log_is_enabled(Info, class, loader, constraints)) {
+            if (lt.is_enabled()) {
               ResourceMark rm;
-              outputStream* out = Log(class, loader, constraints)::info_stream();
-              out->print_cr("purging complete constraint for name %s",
+              lt.print("purging complete constraint for name %s",
                          probe->name()->as_C_string());
             }
 
@@ -174,11 +172,11 @@
 
 void log_ldr_constraint_msg(Symbol* class_name, const char* reason,
                         Handle class_loader1, Handle class_loader2) {
-  if (log_is_enabled(Info, class, loader, constraints)) {
+  LogTarget(Info, class, loader, constraints) lt;
+  if (lt.is_enabled()) {
     ResourceMark rm;
-    outputStream* out = Log(class, loader, constraints)::info_stream();
-    out->print_cr("Failed to add constraint for name: %s, loader[0]: %s,"
-                  " loader[1]: %s, Reason: %s",
+    lt.print("Failed to add constraint for name: %s, loader[0]: %s,"
+                " loader[1]: %s, Reason: %s",
                   class_name->as_C_string(),
                   SystemDictionary::loader_name(class_loader1()),
                   SystemDictionary::loader_name(class_loader2()),
@@ -189,6 +187,7 @@
 bool LoaderConstraintTable::add_entry(Symbol* class_name,
                                       InstanceKlass* klass1, Handle class_loader1,
                                       InstanceKlass* klass2, Handle class_loader2) {
+  LogTarget(Info, class, loader, constraints) lt;
   if (klass1 != NULL && klass2 != NULL) {
     if (klass1 == klass2) {
       // Same type already loaded in both places.  There is no need for any constraint.
@@ -244,10 +243,9 @@
     p->set_klass(klass);
     p->set_next(bucket(index));
     set_entry(index, p);
-    if (log_is_enabled(Info, class, loader, constraints)) {
+    if (lt.is_enabled()) {
       ResourceMark rm;
-      outputStream* out = Log(class, loader, constraints)::info_stream();
-      out->print_cr("adding new constraint for name: %s, loader[0]: %s,"
+      lt.print("adding new constraint for name: %s, loader[0]: %s,"
                     " loader[1]: %s",
                     class_name->as_C_string(),
                     SystemDictionary::loader_name(class_loader1()),
@@ -258,10 +256,9 @@
     /* constraint already imposed */
     if ((*pp1)->klass() == NULL) {
       (*pp1)->set_klass(klass);
-      if (log_is_enabled(Info, class, loader, constraints)) {
+      if (lt.is_enabled()) {
         ResourceMark rm;
-        outputStream* out = Log(class, loader, constraints)::info_stream();
-        out->print_cr("setting class object in existing constraint for"
+        lt.print("setting class object in existing constraint for"
                       " name: %s and loader %s",
                       class_name->as_C_string(),
                       SystemDictionary::loader_name(class_loader1())
@@ -287,12 +284,12 @@
 bool LoaderConstraintTable::check_or_update(InstanceKlass* k,
                                             Handle loader,
                                             Symbol* name) {
+  LogTarget(Info, class, loader, constraints) lt;
   LoaderConstraintEntry* p = *(find_loader_constraint(name, loader));
   if (p && p->klass() != NULL && p->klass() != k) {
-    if (log_is_enabled(Info, class, loader, constraints)) {
+    if (lt.is_enabled()) {
       ResourceMark rm;
-      outputStream* out = Log(class, loader, constraints)::info_stream();
-      out->print_cr("constraint check failed for name %s, loader %s: "
+      lt.print("constraint check failed for name %s, loader %s: "
                  "the presented class object differs from that stored",
                  name->as_C_string(),
                  SystemDictionary::loader_name(loader()));
@@ -301,10 +298,9 @@
   } else {
     if (p && p->klass() == NULL) {
       p->set_klass(k);
-      if (log_is_enabled(Info, class, loader, constraints)) {
+      if (lt.is_enabled()) {
         ResourceMark rm;
-        outputStream* out = Log(class, loader, constraints)::info_stream();
-        out->print_cr("updating constraint for name %s, loader %s, "
+        lt.print("updating constraint for name %s, loader %s, "
                    "by setting class object",
                    name->as_C_string(),
                    SystemDictionary::loader_name(loader()));
@@ -352,10 +348,10 @@
   int num = p->num_loaders();
   p->set_loader(num, loader());
   p->set_num_loaders(num + 1);
-  if (log_is_enabled(Info, class, loader, constraints)) {
+  LogTarget(Info, class, loader, constraints) lt;
+  if (lt.is_enabled()) {
     ResourceMark rm;
-    outputStream* out = Log(class, loader, constraints)::info_stream();
-    out->print_cr("extending constraint for name %s by adding loader[%d]: %s %s",
+    lt.print("extending constraint for name %s by adding loader[%d]: %s %s",
                p->name()->as_C_string(),
                num,
                SystemDictionary::loader_name(loader()),
@@ -392,19 +388,19 @@
     p1->set_num_loaders(num + 1);
   }
 
-  if (log_is_enabled(Info, class, loader, constraints)) {
+  LogTarget(Info, class, loader, constraints) lt;
+  if (lt.is_enabled()) {
     ResourceMark rm;
-    outputStream* out = Log(class, loader, constraints)::info_stream();
-    out->print_cr("merged constraints for name %s, new loader list:",
+    lt.print("merged constraints for name %s, new loader list:",
                   p1->name()->as_C_string()
                   );
 
     for (int i = 0; i < p1->num_loaders(); i++) {
-      out->print_cr("    [%d]: %s", i,
+      lt.print("    [%d]: %s", i,
                     p1->loader_data(i)->loader_name());
     }
     if (p1->klass() == NULL) {
-      out->print_cr("... and setting class object");
+      lt.print("... and setting class object");
     }
   }
 
--- a/src/share/vm/classfile/modules.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/classfile/modules.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -37,6 +37,7 @@
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/instanceKlass.hpp"
 #include "prims/jvm.h"
@@ -436,13 +437,14 @@
 
   log_info(module, load)("%s location: %s", module_name,
                          module_location != NULL ? module_location : "NULL");
-  if (log_is_enabled(Debug, module)) {
-    outputStream* logst = Log(module)::debug_stream();
-    logst->print("define_module(): creation of module: %s, version: %s, location: %s, ",
+  LogTarget(Debug, module) lt;
+  if (lt.is_enabled()) {
+    LogStream ls(lt);
+    ls.print("define_module(): creation of module: %s, version: %s, location: %s, ",
                  module_name, module_version != NULL ? module_version : "NULL",
                  module_location != NULL ? module_location : "NULL");
-    loader_data->print_value_on(logst);
-    logst->print_cr(", package #: %d", pkg_list->length());
+    loader_data->print_value_on(&ls);
+    ls.print_cr(", package #: %d", pkg_list->length());
     for (int y = 0; y < pkg_list->length(); y++) {
       log_trace(module)("define_module(): creation of package %s for module %s",
                         (pkg_list->at(y))->as_C_string(), module_name);
@@ -623,21 +625,22 @@
   assert(module != NULL, "java.lang.Class module field not set");
   assert(java_lang_Module::is_instance(module), "module is not an instance of type java.lang.Module");
 
-  if (log_is_enabled(Debug, module)) {
+  LogTarget(Debug,module) lt;
+  if (lt.is_enabled()) {
     ResourceMark rm(THREAD);
-    outputStream* logst = Log(module)::debug_stream();
+    LogStream ls(lt);
     Klass* klass = java_lang_Class::as_Klass(mirror);
     oop module_name = java_lang_Module::name(module);
     if (module_name != NULL) {
-      logst->print("get_module(): module ");
+      ls.print("get_module(): module ");
       java_lang_String::print(module_name, tty);
     } else {
-      logst->print("get_module(): Unamed Module");
+      ls.print("get_module(): Unamed Module");
     }
     if (klass != NULL) {
-      logst->print_cr(" for class %s", klass->external_name());
+      ls.print_cr(" for class %s", klass->external_name());
     } else {
-      logst->print_cr(" for primitive class");
+      ls.print_cr(" for primitive class");
     }
   }
 
--- a/src/share/vm/classfile/protectionDomainCache.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/classfile/protectionDomainCache.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -25,6 +25,8 @@
 #include "precompiled.hpp"
 #include "classfile/protectionDomainCache.hpp"
 #include "classfile/systemDictionary.hpp"
+#include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/iterator.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
@@ -53,11 +55,12 @@
       if (is_alive->do_object_b(entry->literal())) {
         p = entry->next_addr();
       } else {
-        if (log_is_enabled(Debug, protectiondomain)) {
-          outputStream* log = Log(protectiondomain)::debug_stream();
-          log->print("protection domain unlinked: ");
-          entry->literal()->print_value_on(log);
-          log->cr();
+        LogTarget(Debug, protectiondomain) lt;
+        if (lt.is_enabled()) {
+          LogStream ls(lt);
+          ls.print("protection domain unlinked: ");
+          entry->literal()->print_value_on(&ls);
+          ls.cr();
         }
         *p = entry->next();
         free_entry(entry);
--- a/src/share/vm/classfile/sharedPathsMiscInfo.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/classfile/sharedPathsMiscInfo.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -27,6 +27,7 @@
 #include "classfile/classLoaderData.inline.hpp"
 #include "classfile/sharedPathsMiscInfo.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/metaspaceShared.hpp"
 #include "memory/resourceArea.hpp"
@@ -73,9 +74,7 @@
   return false;
 }
 
-void SharedPathsMiscInfo::print_path(int type, const char* path) {
-  ResourceMark rm;
-  outputStream* out = Log(class, path)::info_stream();
+void SharedPathsMiscInfo::print_path(outputStream* out, int type, const char* path) {
   switch (type) {
   case BOOT:
     out->print("Expecting BOOT path=%s", path);
@@ -106,8 +105,13 @@
     if (!read_jint(&type)) {
       return fail("Corrupted archive file header");
     }
-    log_info(class, path)("type=%s ", type_name(type));
-    print_path(type, path);
+    LogTarget(Info, class, path) lt;
+    if (lt.is_enabled()) {
+      lt.print("type=%s ", type_name(type));
+      LogStream ls(lt);
+      print_path(&ls, type, path);
+      ls.cr();
+    }
     if (!check(type, path)) {
       if (!PrintSharedArchiveAndExit) {
         return false;
--- a/src/share/vm/classfile/sharedPathsMiscInfo.hpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/classfile/sharedPathsMiscInfo.hpp	Fri Jul 21 09:50:12 2017 +0200
@@ -28,6 +28,7 @@
 #include "classfile/classLoader.hpp"
 #include "runtime/os.hpp"
 
+class outputStream;
 // During dumping time, when processing class paths, we build up the dump-time
 // classpath. The JAR files that exist are stored in the list ClassLoader::_first_append_entry.
 // However, we need to store other "misc" information for run-time checking, such as
@@ -139,7 +140,7 @@
     }
   }
 
-  virtual void print_path(int type, const char* path);
+  virtual void print_path(outputStream* os, int type, const char* path);
 
   bool check();
   bool read_jint(jint *ptr) {
--- a/src/share/vm/classfile/systemDictionary.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/classfile/systemDictionary.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -46,6 +46,7 @@
 #include "interpreter/bytecodeStream.hpp"
 #include "interpreter/interpreter.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/filemap.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/resourceArea.hpp"
@@ -432,15 +433,16 @@
 
   // Now we have to call back to java to check if the initating class has access
   JavaValue result(T_VOID);
-  if (log_is_enabled(Debug, protectiondomain)) {
+  LogTarget(Debug, protectiondomain) lt;
+  if (lt.is_enabled()) {
     ResourceMark rm;
     // Print out trace information
-    outputStream* log = Log(protectiondomain)::debug_stream();
-    log->print_cr("Checking package access");
-    log->print("class loader: "); class_loader()->print_value_on(log);
-    log->print(" protection domain: "); protection_domain()->print_value_on(log);
-    log->print(" loading: "); klass->print_value_on(log);
-    log->cr();
+    LogStream ls(lt);
+    ls.print_cr("Checking package access");
+    ls.print("class loader: "); class_loader()->print_value_on(&ls);
+    ls.print(" protection domain: "); protection_domain()->print_value_on(&ls);
+    ls.print(" loading: "); klass->print_value_on(&ls);
+    ls.cr();
   }
 
   InstanceKlass* system_loader = SystemDictionary::ClassLoader_klass();
--- a/src/share/vm/classfile/verifier.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/classfile/verifier.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -34,6 +34,7 @@
 #include "interpreter/bytecodes.hpp"
 #include "interpreter/bytecodeStream.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/instanceKlass.hpp"
@@ -191,11 +192,15 @@
         klass, message_buffer, message_buffer_len, THREAD);
   }
 
-  if (log_is_enabled(Info, class, init)){
-    log_end_verification(Log(class, init)::info_stream(), klassName, exception_name, THREAD);
+  LogTarget(Info, class, init) lt1;
+  if (lt1.is_enabled()) {
+    LogStream ls(lt1);
+    log_end_verification(&ls, klassName, exception_name, THREAD);
   }
-  if (log_is_enabled(Info, verification)){
-    log_end_verification(Log(verification)::info_stream(), klassName, exception_name, THREAD);
+  LogTarget(Info, verification) lt2;
+  if (lt2.is_enabled()) {
+    LogStream ls(lt2);
+    log_end_verification(&ls, klassName, exception_name, THREAD);
   }
 
   if (HAS_PENDING_EXCEPTION) {
@@ -662,9 +667,11 @@
   StackMapTable stackmap_table(&reader, &current_frame, max_locals, max_stack,
                                code_data, code_length, CHECK_VERIFY(this));
 
-  if (log_is_enabled(Info, verification)) {
+  LogTarget(Info, verification) lt;
+  if (lt.is_enabled()) {
     ResourceMark rm(THREAD);
-    stackmap_table.print_on(Log(verification)::info_stream());
+    LogStream ls(lt);
+    stackmap_table.print_on(&ls);
   }
 
   RawBytecodeStream bcs(m);
@@ -704,10 +711,12 @@
       VerificationType type, type2;
       VerificationType atype;
 
-      if (log_is_enabled(Info, verification)) {
+      LogTarget(Info, verification) lt;
+      if (lt.is_enabled()) {
         ResourceMark rm(THREAD);
-        current_frame.print_on(Log(verification)::info_stream());
-        log_info(verification)("offset = %d,  opcode = %s", bci, Bytecodes::name(opcode));
+        LogStream ls(lt);
+        current_frame.print_on(&ls);
+        lt.print("offset = %d,  opcode = %s", bci, Bytecodes::name(opcode));
       }
 
       // Make sure wide instruction is in correct format
--- a/src/share/vm/code/nmethod.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/code/nmethod.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -37,6 +37,7 @@
 #include "compiler/disassembler.hpp"
 #include "interpreter/bytecode.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/methodData.hpp"
 #include "oops/oop.inline.hpp"
@@ -1038,14 +1039,15 @@
   flush_dependencies(is_alive);
 
   // Break cycle between nmethod & method
-  if (log_is_enabled(Trace, class, unload)) {
-    outputStream* log = Log(class, unload)::trace_stream();
-    log->print_cr("making nmethod " INTPTR_FORMAT
+  LogTarget(Trace, class, unload) lt;
+  if (lt.is_enabled()) {
+    LogStream ls(lt);
+    ls.print_cr("making nmethod " INTPTR_FORMAT
                   " unloadable, Method*(" INTPTR_FORMAT
                   "), cause(" INTPTR_FORMAT ")",
                   p2i(this), p2i(_method), p2i(cause));
     if (!Universe::heap()->is_gc_active())
-      cause->klass()->print_on(log);
+      cause->klass()->print_on(&ls);
   }
   // Unlink the osr method, so we do not look this up again
   if (is_osr_method()) {
--- a/src/share/vm/compiler/compileBroker.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/compiler/compileBroker.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -33,6 +33,8 @@
 #include "compiler/compilerOracle.hpp"
 #include "compiler/directivesParser.hpp"
 #include "interpreter/linkResolver.hpp"
+#include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/methodData.hpp"
@@ -1969,7 +1971,8 @@
 
   Log(compilation, codecache) log;
   if (log.is_debug()) {
-    codecache_print(log.debug_stream(), /* detailed= */ false);
+    LogStream ls(log.debug());
+    codecache_print(&ls, /* detailed= */ false);
   }
   if (PrintCodeCacheOnCompilation) {
     codecache_print(/* detailed= */ false);
--- a/src/share/vm/compiler/compileTask.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/compiler/compileTask.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -27,6 +27,8 @@
 #include "compiler/compileLog.hpp"
 #include "compiler/compileBroker.hpp"
 #include "compiler/compilerDirectives.hpp"
+#include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/resourceArea.hpp"
 
 CompileTask*  CompileTask::_task_free_list = NULL;
@@ -425,4 +427,31 @@
   st->cr();
 }
 
+void CompileTask::print_ul(const char* msg){
+  LogTarget(Debug, jit, compilation) lt;
+  if (lt.is_enabled()) {
+    LogStream ls(lt);
+    print(&ls, msg, /* short form */ true, /* cr */ true);
+  }
+}
 
+void CompileTask::print_ul(const nmethod* nm, const char* msg) {
+  LogTarget(Debug, jit, compilation) lt;
+  if (lt.is_enabled()) {
+    LogStream ls(lt);
+    print_impl(&ls, nm->method(), nm->compile_id(),
+               nm->comp_level(), nm->is_osr_method(),
+               nm->is_osr_method() ? nm->osr_entry_bci() : -1,
+               /*is_blocking*/ false,
+               msg, /* short form */ true, /* cr */ true);
+  }
+}
+
+void CompileTask::print_inlining_ul(ciMethod* method, int inline_level, int bci, const char* msg) {
+  LogTarget(Debug, jit, inlining) lt;
+  if (lt.is_enabled()) {
+    LogStream ls(lt);
+    print_inlining_inner(&ls, method, inline_level, bci, msg);
+  }
+}
+
--- a/src/share/vm/compiler/compileTask.hpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/compiler/compileTask.hpp	Fri Jul 21 09:50:12 2017 +0200
@@ -181,27 +181,13 @@
 
 public:
   void         print(outputStream* st = tty, const char* msg = NULL, bool short_form = false, bool cr = true);
-  void         print_ul(const char* msg = NULL){
-    Log(jit, compilation) log;
-    if (log.is_debug()) {
-      print(log.debug_stream(), msg, /* short form */ true, /* cr */ true);
-    }
-  }
+  void         print_ul(const char* msg = NULL);
   static void  print(outputStream* st, const nmethod* nm, const char* msg = NULL, bool short_form = false, bool cr = true) {
     print_impl(st, nm->method(), nm->compile_id(), nm->comp_level(),
                            nm->is_osr_method(), nm->is_osr_method() ? nm->osr_entry_bci() : -1, /*is_blocking*/ false,
                            msg, short_form, cr);
   }
-  static void  print_ul(const nmethod* nm, const char* msg = NULL) {
-    Log(jit, compilation) log;
-    if (log.is_debug()) {
-      print_impl(log.debug_stream(), nm->method(), nm->compile_id(),
-                 nm->comp_level(), nm->is_osr_method(),
-                 nm->is_osr_method() ? nm->osr_entry_bci() : -1,
-                 /*is_blocking*/ false,
-                 msg, /* short form */ true, /* cr */ true);
-    }
-  }
+  static void  print_ul(const nmethod* nm, const char* msg = NULL);
 
   static void  print_inline_indent(int inline_level, outputStream* st = tty);
 
@@ -223,12 +209,7 @@
   static void print_inlining_tty(ciMethod* method, int inline_level, int bci, const char* msg = NULL) {
     print_inlining_inner(tty, method, inline_level, bci, msg);
   }
-  static void print_inlining_ul(ciMethod* method, int inline_level, int bci, const char* msg = NULL) {
-    Log(jit, inlining) log;
-    if (log.is_debug()) {
-      print_inlining_inner(log.debug_stream(), method, inline_level, bci, msg);
-    }
-  }
+  static void print_inlining_ul(ciMethod* method, int inline_level, int bci, const char* msg = NULL);
 };
 
 #endif // SHARE_VM_COMPILER_COMPILETASK_HPP
--- a/src/share/vm/gc/cms/compactibleFreeListSpace.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/gc/cms/compactibleFreeListSpace.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -32,7 +32,8 @@
 #include "gc/shared/genCollectedHeap.hpp"
 #include "gc/shared/space.inline.hpp"
 #include "gc/shared/spaceDecorator.hpp"
-#include "logging/logStream.inline.hpp"
+#include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.inline.hpp"
@@ -2194,8 +2195,8 @@
                 " Previous: addr = " PTR_FORMAT ", size = " SIZE_FORMAT ", obj = %s, live = %s \n",
         p2i(addr),       res,        was_obj      ?"true":"false", was_live      ?"true":"false",
         p2i(_last_addr), _last_size, _last_was_obj?"true":"false", _last_was_live?"true":"false");
-      ResourceMark rm;
-      _sp->print_on(log.error_stream());
+      LogStream ls(log.error());
+      _sp->print_on(&ls);
       guarantee(false, "Verification failed.");
     }
     _last_addr = addr;
@@ -2369,7 +2370,8 @@
   AdaptiveFreeList<FreeChunk> total;
   log.print("end sweep# " SIZE_FORMAT, sweep_count);
   ResourceMark rm;
-  outputStream* out = log.stream();
+  LogStream ls(log);
+  outputStream* out = &ls;
   AdaptiveFreeList<FreeChunk>::print_labels_on(out, "size");
   size_t total_free = 0;
   for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
--- a/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -55,6 +55,7 @@
 #include "gc/shared/strongRootsScope.hpp"
 #include "gc/shared/taskqueue.inline.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/allocation.hpp"
 #include "memory/iterator.inline.hpp"
 #include "memory/padded.hpp"
@@ -695,8 +696,8 @@
 void ConcurrentMarkSweepGeneration::promotion_failure_occurred() {
   Log(gc, promotion) log;
   if (log.is_trace()) {
-    ResourceMark rm;
-    cmsSpace()->dump_at_safepoint_with_locks(collector(), log.trace_stream());
+    LogStream ls(log.trace());
+    cmsSpace()->dump_at_safepoint_with_locks(collector(), &ls);
   }
 }
 
@@ -2247,7 +2248,8 @@
     if (!_marks->isMarked(addr)) {
       Log(gc, verify) log;
       ResourceMark rm;
-      oop(addr)->print_on(log.error_stream());
+      LogStream ls(log.error());
+      oop(addr)->print_on(&ls);
       log.error(" (" INTPTR_FORMAT " should have been marked)", p2i(addr));
       _failed = true;
     }
@@ -2372,7 +2374,8 @@
     Log(gc, verify) log;
     log.error("Failed marking verification after remark");
     ResourceMark rm;
-    gch->print_on(log.error_stream());
+    LogStream ls(log.error());
+    gch->print_on(&ls);
     fatal("CMS: failed marking verification after remark");
   }
 }
@@ -5873,7 +5876,8 @@
     if (!_cms_bm->isMarked(addr)) {
       Log(gc, verify) log;
       ResourceMark rm;
-      oop(addr)->print_on(log.error_stream());
+      LogStream ls(log.error());
+      oop(addr)->print_on(&ls);
       log.error(" (" INTPTR_FORMAT " should have been marked)", p2i(addr));
       fatal("... aborting");
     }
@@ -6652,7 +6656,8 @@
     if (!_cms_bm->isMarked(addr)) {
       Log(gc, verify) log;
       ResourceMark rm;
-      oop(addr)->print_on(log.error_stream());
+      LogStream ls(log.error());
+      oop(addr)->print_on(&ls);
       log.error(" (" INTPTR_FORMAT " should have been marked)", p2i(addr));
       fatal("... aborting");
     }
@@ -7059,7 +7064,8 @@
     Log(gc, sweep) log;
     log.error("inFreeRange() should have been reset; dumping state of SweepClosure");
     ResourceMark rm;
-    print_on(log.error_stream());
+    LogStream ls(log.error());
+    print_on(&ls);
     ShouldNotReachHere();
   }
 
--- a/src/share/vm/gc/cms/parNewGeneration.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/gc/cms/parNewGeneration.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -47,6 +47,7 @@
 #include "gc/shared/taskqueue.inline.hpp"
 #include "gc/shared/workgroup.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/objArrayOop.hpp"
 #include "oops/oop.inline.hpp"
@@ -407,7 +408,8 @@
   }
 
   ResourceMark rm;
-  outputStream* st = log.debug_stream();
+  LogStream ls(log.debug());
+  outputStream* st = &ls;
 
   print_termination_stats_hdr(st);
 
@@ -435,7 +437,8 @@
   }
   Log(gc, task, stats) log;
   ResourceMark rm;
-  outputStream* st = log.trace_stream();
+  LogStream ls(log.trace());
+  outputStream* st = &ls;
   print_taskqueue_stats_hdr(st);
 
   TaskQueueStats totals;
--- a/src/share/vm/gc/cms/parOopClosures.inline.hpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/gc/cms/parOopClosures.inline.hpp	Fri Jul 21 09:50:12 2017 +0200
@@ -31,6 +31,7 @@
 #include "gc/shared/genCollectedHeap.hpp"
 #include "gc/shared/genOopClosures.inline.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 
 template <class T> inline void ParScanWeakRefClosure::do_oop_work(T* p) {
   assert (!oopDesc::is_null(*p), "null weak reference?");
@@ -90,11 +91,12 @@
         assert((HeapWord*)obj < (HeapWord*)p, "Error");
         log.error("Object: " PTR_FORMAT, p2i((void *)obj));
         log.error("-------");
-        obj->print_on(log.error_stream());
+        LogStream ls(log.error());
+        obj->print_on(&ls);
         log.error("-----");
         log.error("Heap:");
         log.error("-----");
-        gch->print_on(log.error_stream());
+        gch->print_on(&ls);
         ShouldNotReachHere();
       }
 #endif
--- a/src/share/vm/gc/g1/g1AllocRegion.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/gc/g1/g1AllocRegion.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -26,6 +26,8 @@
 #include "gc/g1/g1AllocRegion.inline.hpp"
 #include "gc/g1/g1EvacStats.inline.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
+#include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/orderAccess.inline.hpp"
 #include "utilities/align.hpp"
@@ -212,12 +214,9 @@
 
   if ((actual_word_size == 0 && result == NULL) || detailed_info) {
     ResourceMark rm;
-    outputStream* out;
-    if (detailed_info) {
-      out = log.trace_stream();
-    } else {
-      out = log.debug_stream();
-    }
+    LogStream ls_trace(log.trace());
+    LogStream ls_debug(log.debug());
+    outputStream* out = detailed_info ? &ls_trace : &ls_debug;
 
     out->print("%s: %u ", _name, _count);
 
--- a/src/share/vm/gc/g1/g1CollectedHeap.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/gc/g1/g1CollectedHeap.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -2495,10 +2495,10 @@
 }
 
 void G1CollectedHeap::print_heap_regions() const {
-  Log(gc, heap, region) log;
-  if (log.is_trace()) {
-    ResourceMark rm;
-    print_regions_on(log.trace_stream());
+  LogTarget(Trace, gc, heap, region) lt;
+  if (lt.is_enabled()) {
+    LogStream ls(lt);
+    print_regions_on(&ls);
   }
 }
 
@@ -2917,7 +2917,8 @@
   }
   Log(gc, task, stats) log;
   ResourceMark rm;
-  outputStream* st = log.trace_stream();
+  LogStream ls(log.trace());
+  outputStream* st = &ls;
 
   print_taskqueue_stats_hdr(st);
 
--- a/src/share/vm/gc/g1/g1GCPhaseTimes.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/gc/g1/g1GCPhaseTimes.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -30,6 +30,7 @@
 #include "gc/g1/workerDataArray.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "runtime/timer.hpp"
 #include "runtime/os.hpp"
 #include "utilities/macros.hpp"
@@ -233,11 +234,11 @@
 
 template <class T>
 void G1GCPhaseTimes::details(T* phase, const char* indent) const {
-  Log(gc, phases, task) log;
-  if (log.is_level(LogLevel::Trace)) {
-    outputStream* trace_out = log.trace_stream();
-    trace_out->print("%s", indent);
-    phase->print_details_on(trace_out);
+  LogTarget(Trace, gc, phases, task) lt;
+  if (lt.is_enabled()) {
+    LogStream ls(lt);
+    ls.print("%s", indent);
+    phase->print_details_on(&ls);
   }
 }
 
@@ -257,18 +258,19 @@
 }
 
 void G1GCPhaseTimes::debug_phase(WorkerDataArray<double>* phase) const {
-  Log(gc, phases) log;
-  if (log.is_level(LogLevel::Debug)) {
+  LogTarget(Debug, gc, phases) lt;
+  if (lt.is_enabled()) {
     ResourceMark rm;
-    log_phase(phase, 2, log.debug_stream(), true);
+    LogStream ls(lt);
+    log_phase(phase, 2, &ls, true);
   }
 }
 
 void G1GCPhaseTimes::trace_phase(WorkerDataArray<double>* phase, bool print_sum) const {
-  Log(gc, phases) log;
-  if (log.is_level(LogLevel::Trace)) {
-    ResourceMark rm;
-    log_phase(phase, 3, log.trace_stream(), print_sum);
+  LogTarget(Trace, gc, phases) lt;
+  if (lt.is_enabled()) {
+    LogStream ls(lt);
+    log_phase(phase, 3, &ls, print_sum);
   }
 }
 
--- a/src/share/vm/gc/g1/g1HeapVerifier.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/gc/g1/g1HeapVerifier.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -23,7 +23,6 @@
  */
 
 #include "precompiled.hpp"
-#include "logging/log.hpp"
 #include "gc/g1/concurrentMarkThread.hpp"
 #include "gc/g1/g1Allocator.inline.hpp"
 #include "gc/g1/g1CollectedHeap.hpp"
@@ -36,6 +35,8 @@
 #include "gc/g1/heapRegion.inline.hpp"
 #include "gc/g1/heapRegionRemSet.hpp"
 #include "gc/g1/g1StringDedup.hpp"
+#include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
 
@@ -66,7 +67,8 @@
           log.error("  Mark word: " PTR_FORMAT, p2i(obj->mark()));
         }
         ResourceMark rm;
-        obj->print_on(log.error_stream());
+        LogStream ls(log.error());
+        obj->print_on(&ls);
         _failures = true;
       }
     }
@@ -408,7 +410,8 @@
     // print_extended_on() instead of print_on().
     Log(gc, verify) log;
     ResourceMark rm;
-    _g1h->print_extended_on(log.error_stream());
+    LogStream ls(log.error());
+    _g1h->print_extended_on(&ls);
   }
   guarantee(!failures, "there should not have been any failures");
 }
--- a/src/share/vm/gc/g1/g1RemSet.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/gc/g1/g1RemSet.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -730,7 +730,8 @@
     Log(gc, remset) log;
     log.trace("%s", header);
     ResourceMark rm;
-    _prev_period_summary.print_on(log.trace_stream());
+    LogStream ls(log.trace());
+    _prev_period_summary.print_on(&ls);
 
     _prev_period_summary.set(&current);
   }
@@ -742,7 +743,8 @@
     log.trace(" Cumulative RS summary");
     G1RemSetSummary current(this);
     ResourceMark rm;
-    current.print_on(log.trace_stream());
+    LogStream ls(log.trace());
+    current.print_on(&ls);
   }
 }
 
--- a/src/share/vm/gc/g1/heapRegion.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/gc/g1/heapRegion.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -36,6 +36,7 @@
 #include "gc/shared/genOopClosures.inline.hpp"
 #include "gc/shared/space.inline.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/iterator.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
@@ -527,17 +528,19 @@
           HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
           log.error("Field " PTR_FORMAT " of live obj " PTR_FORMAT " in region [" PTR_FORMAT ", " PTR_FORMAT ")",
             p2i(p), p2i(_containing_obj), p2i(from->bottom()), p2i(from->end()));
-          print_object(log.error_stream(), _containing_obj);
+          LogStream ls(log.error());
+          print_object(&ls, _containing_obj);
           log.error("points to obj " PTR_FORMAT " not in the heap", p2i(obj));
         } else {
           HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
           HeapRegion* to = _g1h->heap_region_containing((HeapWord*)obj);
           log.error("Field " PTR_FORMAT " of live obj " PTR_FORMAT " in region [" PTR_FORMAT ", " PTR_FORMAT ")",
             p2i(p), p2i(_containing_obj), p2i(from->bottom()), p2i(from->end()));
-          print_object(log.error_stream(), _containing_obj);
+          LogStream ls(log.error());
+          print_object(&ls, _containing_obj);
           log.error("points to dead obj " PTR_FORMAT " in region [" PTR_FORMAT ", " PTR_FORMAT ")",
             p2i(obj), p2i(to->bottom()), p2i(to->end()));
-          print_object(log.error_stream(), obj);
+          print_object(&ls, obj);
         }
         log.error("----------");
         _failures = true;
@@ -593,10 +596,11 @@
           log.error("Field " PTR_FORMAT " of obj " PTR_FORMAT ", in region " HR_FORMAT,
             p2i(p), p2i(_containing_obj), HR_FORMAT_PARAMS(from));
           ResourceMark rm;
-          _containing_obj->print_on(log.error_stream());
+          LogStream ls(log.error());
+          _containing_obj->print_on(&ls);
           log.error("points to obj " PTR_FORMAT " in region " HR_FORMAT, p2i(obj), HR_FORMAT_PARAMS(to));
           if (obj->is_oop()) {
-            obj->print_on(log.error_stream());
+            obj->print_on(&ls);
           }
           log.error("Obj head CTE = %d, field CTE = %d.", cv_obj, cv_field);
           log.error("----------");
--- a/src/share/vm/gc/parallel/adjoiningGenerations.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/gc/parallel/adjoiningGenerations.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -28,6 +28,7 @@
 #include "gc/parallel/generationSizer.hpp"
 #include "gc/parallel/parallelScavengeHeap.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/resourceArea.hpp"
 #include "utilities/align.hpp"
 #include "utilities/ostream.hpp"
@@ -129,7 +130,8 @@
   log.debug("  Requested change: " SIZE_FORMAT_HEX "  Attempted change: " SIZE_FORMAT_HEX,
                         expand_in_bytes, change_in_bytes);
   ResourceMark rm;
-  ParallelScavengeHeap::heap()->print_on(log.debug_stream());
+  LogStream ls(log.debug());
+  ParallelScavengeHeap::heap()->print_on(&ls);
   log.debug("  PS%sGen max size: " SIZE_FORMAT "K", old ? "Old" : "Young", max_size/K);
 }
 
@@ -140,7 +142,8 @@
   }
   log.debug("After expansion of %s gen with boundary move", old ? "old" : "young");
   ResourceMark rm;
-  ParallelScavengeHeap::heap()->print_on(log.debug_stream());
+  LogStream ls(log.debug());
+  ParallelScavengeHeap::heap()->print_on(&ls);
   log.debug("  PS%sGen max size: " SIZE_FORMAT "K", old ? "Old" : "Young", max_size/K);
 }
 
--- a/src/share/vm/gc/parallel/gcTaskManager.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/gc/parallel/gcTaskManager.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -28,6 +28,7 @@
 #include "gc/shared/gcId.hpp"
 #include "gc/shared/workerManager.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/allocation.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
@@ -437,13 +438,12 @@
 
     Log(gc, task, thread) log;
     if (log.is_trace()) {
-      ResourceMark rm;
-      outputStream* out = log.trace_stream();
-      out->print("GCTaskManager::initialize: distribution:");
+      LogStream ls(log.trace());
+      ls.print("GCTaskManager::initialize: distribution:");
       for (uint t = 0; t < workers(); t += 1) {
-        out->print("  %u", _processor_assignment[t]);
+        ls.print("  %u", _processor_assignment[t]);
       }
-      out->cr();
+      ls.cr();
     }
   }
   reset_busy_workers();
--- a/src/share/vm/gc/parallel/psParallelCompact.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/gc/parallel/psParallelCompact.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -206,7 +206,8 @@
   }
   Log(gc, compaction) log;
   ResourceMark rm;
-  Universe::print_on(log.trace_stream());
+  LogStream ls(log.trace());
+  Universe::print_on(&ls);
   log.trace("space  bottom     top        end        new_top");
   log.trace("------ ---------- ---------- ---------- ----------");
 
@@ -2372,7 +2373,8 @@
 
   Log(gc, compaction) log;
   ResourceMark rm;
-  outputStream* out = log.trace_stream();
+  LogStream ls(log.trace());
+  outputStream* out = &ls;
 
   typedef ParallelCompactData::RegionData rd_t;
   ParallelCompactData& sd = summary_data();
--- a/src/share/vm/gc/parallel/psPromotionManager.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/gc/parallel/psPromotionManager.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -33,6 +33,7 @@
 #include "gc/shared/preservedMarks.inline.hpp"
 #include "gc/shared/taskqueue.inline.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/memRegion.hpp"
 #include "memory/padded.inline.hpp"
@@ -155,7 +156,8 @@
   }
   Log(gc, task, stats) log;
   ResourceMark rm;
-  outputStream* out = log.trace_stream();
+  LogStream ls(log.trace());
+  outputStream* out = &ls;
   out->print_cr("== GC Tasks Stats, GC %3d",
                 ParallelScavengeHeap::heap()->total_collections());
 
--- a/src/share/vm/gc/shared/collectedHeap.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/gc/shared/collectedHeap.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -594,11 +594,12 @@
     HeapDumper::dump_heap();
   }
 
-  Log(gc, classhisto) log;
-  if (log.is_trace()) {
+  LogTarget(Trace, gc, classhisto) lt;
+  if (lt.is_enabled()) {
     GCTraceTime(Trace, gc, classhisto) tm(before ? "Class Histogram (before full gc)" : "Class Histogram (after full gc)", timer);
     ResourceMark rm;
-    VM_GC_HeapInspection inspector(log.trace_stream(), false /* ! full gc */);
+    LogStream ls(lt);
+    VM_GC_HeapInspection inspector(&ls, false /* ! full gc */);
     inspector.doit();
   }
 }
--- a/src/share/vm/gc/shared/gcTraceTime.inline.hpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/gc/shared/gcTraceTime.inline.hpp	Fri Jul 21 09:50:12 2017 +0200
@@ -30,7 +30,7 @@
 #include "gc/shared/gcTrace.hpp"
 #include "gc/shared/gcTraceTime.hpp"
 #include "logging/log.hpp"
-#include "logging/logStream.inline.hpp"
+#include "logging/logStream.hpp"
 #include "memory/universe.hpp"
 #include "prims/jni_md.h"
 #include "utilities/ticks.hpp"
--- a/src/share/vm/interpreter/linkResolver.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/interpreter/linkResolver.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -34,6 +34,7 @@
 #include "interpreter/interpreterRuntime.hpp"
 #include "interpreter/linkResolver.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.inline.hpp"
 #include "oops/instanceKlass.hpp"
@@ -767,11 +768,15 @@
                                     int index = -1) {
 #ifndef PRODUCT
   ResourceMark rm;
+  Log(itables) logi;
+  LogStream lsi(logi.trace());
+  Log(vtables) logv;
+  LogStream lsv(logv.trace());
   outputStream* st;
   if (logitables) {
-    st = Log(itables)::trace_stream();
+    st = &lsi;
   } else {
-    st = Log(vtables)::trace_stream();
+    st = &lsv;
   }
   st->print("%s%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
             prefix,
--- a/src/share/vm/logging/log.hpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/logging/log.hpp	Fri Jul 21 09:50:12 2017 +0200
@@ -105,10 +105,6 @@
 //
 #define LogTarget(level, ...) LogTargetImpl<LogLevel::level, LOG_TAGS(__VA_ARGS__)>
 
-// Forward declaration to decouple this file from the outputStream API.
-class outputStream;
-outputStream* create_log_stream(LogLevelType level, LogTagSet* tagset);
-
 template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
 class LogTargetImpl;
 
@@ -173,9 +169,6 @@
   static bool is_##name() { \
     return is_level(LogLevel::level); \
   } \
-  static outputStream* name##_stream() { \
-    return create_log_stream(LogLevel::level, &LogTagSetMapping<T0, T1, T2, T3, T4>::tagset()); \
-  } \
   static LogTargetImpl<LogLevel::level, T0, T1, T2, T3, T4, GuardTag>* name() { \
     return (LogTargetImpl<LogLevel::level, T0, T1, T2, T3, T4, GuardTag>*)NULL; \
   }
@@ -204,9 +197,6 @@
     va_end(args);
   }
 
-  static outputStream* stream() {
-    return create_log_stream(level, &LogTagSetMapping<T0, T1, T2, T3, T4>::tagset());
-  }
 };
 
 #endif // SHARE_VM_LOGGING_LOG_HPP
--- a/src/share/vm/logging/logHandle.hpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/logging/logHandle.hpp	Fri Jul 21 09:50:12 2017 +0200
@@ -95,11 +95,6 @@
     return _tagset->is_level(_level);
   }
 
-  // Creates a log stream from the information stored in this instance.
-  // Callers need a ResourceMark on the stack.
-  outputStream* stream() {
-    return create_log_stream(_level, _tagset);;
-  }
 };
 
 #endif // SHARE_VM_LOGGING_LOGHANDLE_HPP
--- a/src/share/vm/logging/logStream.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/logging/logStream.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -24,11 +24,91 @@
 
 #include "precompiled.hpp"
 #include "logging/log.hpp"
-#include "logging/logStream.inline.hpp"
+#include "logging/logStream.hpp"
 
-// Create a log stream without an embedded ResourceMark.
-// The function is placed here to be called out-of-line in log.hpp.
-outputStream* create_log_stream(LogLevelType level, LogTagSet* tagset) {
-  return new LogStreamNoResourceMark(level, tagset);
+LogStream::LineBuffer::LineBuffer()
+ : _buf(_smallbuf), _cap(sizeof(_smallbuf)), _pos(0)
+{
+  _buf[0] = '\0';
 }
 
+LogStream::LineBuffer::~LineBuffer() {
+  assert(_pos == 0, "still outstanding bytes in the line buffer");
+  if (_buf != _smallbuf) {
+    os::free(_buf);
+  }
+}
+
+// try_ensure_cap tries to enlarge the capacity of the internal buffer
+// to the given atleast value. May fail if either OOM happens or atleast
+// is larger than a reasonable max of 1 M. Caller must not assume
+// capacity without checking.
+void LogStream::LineBuffer::try_ensure_cap(size_t atleast) {
+  assert(_cap >= sizeof(_smallbuf), "sanity");
+  if (_cap < atleast) {
+    // Cap out at a reasonable max to prevent runaway leaks.
+    const size_t reasonable_max = 1 * M;
+    assert(_cap <= reasonable_max, "sanity");
+    if (_cap == reasonable_max) {
+      return;
+    }
+
+    const size_t additional_expansion = 256;
+    size_t newcap = align_up(atleast + additional_expansion, additional_expansion);
+    if (newcap > reasonable_max) {
+      log_info(logging)("Suspiciously long log line: \"%.100s%s",
+              _buf, (_pos >= 100 ? "..." : ""));
+      newcap = reasonable_max;
+    }
+
+    char* const newbuf = (char*) os::malloc(newcap, mtLogging);
+    if (newbuf == NULL) { // OOM. Leave object unchanged.
+      return;
+    }
+    if (_pos > 0) { // preserve old content
+      memcpy(newbuf, _buf, _pos + 1); // ..including trailing zero
+    }
+    if (_buf != _smallbuf) {
+      os::free(_buf);
+    }
+    _buf = newbuf;
+    _cap = newcap;
+  }
+  assert(_cap >= atleast, "sanity");
+}
+
+void LogStream::LineBuffer::append(const char* s, size_t len) {
+  assert(_buf[_pos] == '\0', "sanity");
+  assert(_pos < _cap, "sanity");
+  const size_t minimum_capacity_needed = _pos + len + 1;
+  try_ensure_cap(minimum_capacity_needed);
+  // try_ensure_cap may not have enlarged the capacity to the full requested
+  // extend or may have not worked at all. In that case, just gracefully work
+  // with what we have already; just truncate if necessary.
+  if (_cap < minimum_capacity_needed) {
+    len = _cap - _pos - 1;
+    if (len == 0) {
+      return;
+    }
+  }
+  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.buffer());
+    _current_line.reset();
+  } else {
+    _current_line.append(s, len);
+  }
+  update_position(s, len);
+}
+
--- a/src/share/vm/logging/logStream.hpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/logging/logStream.hpp	Fri Jul 21 09:50:12 2017 +0200
@@ -30,19 +30,42 @@
 #include "memory/resourceArea.hpp"
 #include "utilities/ostream.hpp"
 
-// The base class of an output stream that logs to the logging framework.
-template <class streamClass>
-class LogStreamBase : public outputStream {
-  streamClass     _current_line;
+
+class LogStream : public outputStream {
+  friend class LogStreamTest_TestLineBufferAllocation_test_vm_Test; // see test/native/logging/test_logStream.cpp
+  friend class LogStreamTest_TestLineBufferAllocationCap_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
+  // is allocated on the stack, this means small lines are assembled
+  // directly on the stack.
+  class LineBuffer {
+    char _smallbuf[64];
+    char* _buf;
+    size_t _cap;
+    size_t _pos;
+    void try_ensure_cap(size_t cap);
+  public:
+    LineBuffer();
+    ~LineBuffer();
+    const char* buffer() 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.
   //
   // LogTarget(Debug, gc) log;
   // LogStreamBase(log) stream;
   template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
-  LogStreamBase(const LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>& type_carrier) :
+  LogStream(const LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>& type_carrier) :
       _log_handle(level, &LogTagSetMapping<T0, T1, T2, T3, T4>::tagset()) {}
 
   // Constructor to support creation from typed (likely NULL) pointer. Mostly used by the logging framework.
@@ -51,7 +74,7 @@
   //  or
   // LogStreamBase stream((LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>*)NULL);
   template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
-  LogStreamBase(const LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>* type_carrier) :
+  LogStream(const LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>* type_carrier) :
       _log_handle(level, &LogTagSetMapping<T0, T1, T2, T3, T4>::tagset()) {}
 
   // Constructor to support creation from a LogTargetHandle.
@@ -59,60 +82,16 @@
   // LogTarget(Debug, gc) log;
   // LogTargetHandle(log) handle;
   // LogStreamBase stream(handle);
-  LogStreamBase(LogTargetHandle handle) : _log_handle(handle) {}
+  LogStream(LogTargetHandle handle) : _log_handle(handle) {}
 
   // Constructor to support creation from a log level and tagset.
   //
   // LogStreamBase(level, tageset);
-  LogStreamBase(LogLevelType level, LogTagSet* tagset) : _log_handle(level, tagset) {}
+  LogStream(LogLevelType level, LogTagSet* tagset) : _log_handle(level, tagset) {}
 
-  ~LogStreamBase() {
-    guarantee(_current_line.size() == 0, "Buffer not flushed. Missing call to print_cr()?");
-  }
-
-public:
   void write(const char* s, size_t len);
 };
 
-// A stringStream with an embedded ResourceMark.
-class stringStreamWithResourceMark : outputStream {
- private:
-  // The stringStream Resource allocate in the constructor,
-  // so the order of the fields is important.
-  ResourceMark _embedded_resource_mark;
-  stringStream _stream;
-
- public:
-  stringStreamWithResourceMark(size_t initial_bufsize = 256) :
-      _embedded_resource_mark(),
-      _stream(initial_bufsize) {}
-
-  virtual void write(const char* c, size_t len) { _stream.write(c, len); }
-  size_t      size()                            { return _stream.size(); }
-  const char* base()                            { return _stream.base(); }
-  void  reset()                                 { _stream.reset(); }
-  char* as_string()                             { return _stream.as_string(); }
-};
-
-// An output stream that logs to the logging framework.
-//
-// The backing buffer is allocated in Resource memory.
-// The caller is required to have a ResourceMark on the stack.
-typedef LogStreamBase<stringStream> LogStreamNoResourceMark;
-
-// An output stream that logs to the logging framework.
-//
-// The backing buffer is allocated in CHeap memory.
-typedef LogStreamBase<bufferedStream> LogStreamCHeap;
-
-// An output stream that logs to the logging framework, and embeds a ResourceMark.
-//
-// The backing buffer is allocated in Resource memory.
-// The class is intended to be stack allocated.
-// The class provides its own ResourceMark,
-//  so care needs to be taken when nested ResourceMarks are used.
-typedef LogStreamBase<stringStreamWithResourceMark> LogStream;
-
 // Support creation of a LogStream without having to provide a LogTarget pointer.
 #define LogStreamHandle(level, ...) LogStreamTemplate<LogLevel::level, LOG_TAGS(__VA_ARGS__)>
 
--- a/src/share/vm/logging/logStream.inline.hpp	Thu Jul 20 17:23:24 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-#ifndef SHARE_VM_LOGGING_LOGSTREAM_INLINE_HPP
-#define SHARE_VM_LOGGING_LOGSTREAM_INLINE_HPP
-
-#include "logging/log.hpp"
-#include "logging/logHandle.hpp"
-#include "logging/logStream.hpp"
-#include "memory/resourceArea.hpp"
-#include "utilities/ostream.hpp"
-
-template <class streamClass>
-inline void LogStreamBase<streamClass>::write(const char* s, size_t len) {
-  if (len > 0 && s[len - 1] == '\n') {
-    _current_line.write(s, len - 1);
-    _current_line.write("\0", 1);
-    _log_handle.print("%s", _current_line.base());
-    _current_line.reset();
-  } else {
-    _current_line.write(s, len);
-  }
-  update_position(s, len);
-}
-
-#endif // SHARE_VM_LOGGING_LOGSTREAM_INLINE_HPP
--- a/src/share/vm/memory/binaryTreeDictionary.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/memory/binaryTreeDictionary.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -25,7 +25,8 @@
 #include "precompiled.hpp"
 #include "gc/cms/allocationStats.hpp"
 #include "gc/shared/spaceDecorator.hpp"
-#include "logging/logStream.inline.hpp"
+#include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/binaryTreeDictionary.hpp"
 #include "memory/freeList.hpp"
 #include "memory/metachunk.hpp"
--- a/src/share/vm/memory/filemap.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/memory/filemap.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -33,6 +33,7 @@
 #include "gc/g1/g1CollectedHeap.hpp"
 #endif
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "logging/logMessage.hpp"
 #include "memory/filemap.hpp"
 #include "memory/metadataFactory.hpp"
@@ -104,9 +105,9 @@
     } else {
       if (log_is_enabled(Info, cds)) {
         ResourceMark rm;
-        outputStream* logstream = Log(cds)::info_stream();
-        logstream->print("UseSharedSpaces: ");
-        logstream->vprint_cr(msg, ap);
+        LogStream ls(Log(cds)::info());
+        ls.print("UseSharedSpaces: ");
+        ls.vprint_cr(msg, ap);
       }
     }
     UseSharedSpaces = false;
--- a/src/share/vm/memory/metaspace.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/memory/metaspace.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -27,6 +27,7 @@
 #include "gc/shared/collectorPolicy.hpp"
 #include "gc/shared/gcLocker.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/allocation.hpp"
 #include "memory/binaryTreeDictionary.hpp"
 #include "memory/filemap.hpp"
@@ -1008,11 +1009,13 @@
       "The committed memory doesn't match the expanded memory.");
 
   if (!is_available(chunk_word_size)) {
-    Log(gc, metaspace, freelist) log;
-    log.debug("VirtualSpaceNode::take_from_committed() not available " SIZE_FORMAT " words ", chunk_word_size);
-    // Dump some information about the virtual space that is nearly full
-    ResourceMark rm;
-    print_on(log.debug_stream());
+    LogTarget(Debug, gc, metaspace, freelist) lt;
+    if (lt.is_enabled()) {
+      LogStream ls(lt);
+      ls.print("VirtualSpaceNode::take_from_committed() not available " SIZE_FORMAT " words ", chunk_word_size);
+      // Dump some information about the virtual space that is nearly full
+      print_on(&ls);
+    }
     return NULL;
   }
 
@@ -1347,11 +1350,12 @@
 #ifdef ASSERT
   new_entry->mangle();
 #endif
-  if (log_is_enabled(Trace, gc, metaspace)) {
-    Log(gc, metaspace) log;
+  LogTarget(Trace, gc, metaspace) lt;
+  if (lt.is_enabled()) {
+    LogStream ls(lt);
     VirtualSpaceNode* vsl = current_virtual_space();
     ResourceMark rm;
-    vsl->print_on(log.trace_stream());
+    vsl->print_on(&ls);
   }
 }
 
@@ -1951,8 +1955,8 @@
   assert((word_size <= chunk->word_size()) ||
          (list_index(chunk->word_size()) == HumongousIndex),
          "Non-humongous variable sized chunk");
-  Log(gc, metaspace, freelist) log;
-  if (log.is_debug()) {
+  LogTarget(Debug, gc, metaspace, freelist) lt;
+  if (lt.is_enabled()) {
     size_t list_count;
     if (list_index(word_size) < HumongousIndex) {
       ChunkList* list = find_free_chunks_list(word_size);
@@ -1960,10 +1964,11 @@
     } else {
       list_count = humongous_dictionary()->total_count();
     }
-    log.debug("ChunkManager::chunk_freelist_allocate: " PTR_FORMAT " chunk " PTR_FORMAT "  size " SIZE_FORMAT " count " SIZE_FORMAT " ",
-               p2i(this), p2i(chunk), chunk->word_size(), list_count);
+    LogStream ls(lt);
+    ls.print("ChunkManager::chunk_freelist_allocate: " PTR_FORMAT " chunk " PTR_FORMAT "  size " SIZE_FORMAT " count " SIZE_FORMAT " ",
+             p2i(this), p2i(chunk), chunk->word_size(), list_count);
     ResourceMark rm;
-    locked_print_free_chunks(log.debug_stream());
+    locked_print_free_chunks(&ls);
   }
 
   return chunk;
@@ -2390,10 +2395,11 @@
   if (log.is_trace()) {
     log.trace("~SpaceManager(): " PTR_FORMAT, p2i(this));
     ResourceMark rm;
-    locked_print_chunks_in_use_on(log.trace_stream());
+    LogStream ls(log.trace());
+    locked_print_chunks_in_use_on(&ls);
     if (block_freelists() != NULL) {
-    block_freelists()->print_on(log.trace_stream());
-  }
+      block_freelists()->print_on(&ls);
+    }
   }
 
   // Add all the chunks in use by this space manager
@@ -2469,9 +2475,9 @@
   if (log.is_trace()) {
     log.trace("SpaceManager::add_chunk: " SIZE_FORMAT ") ", sum_count_in_chunks_in_use());
     ResourceMark rm;
-    outputStream* out = log.trace_stream();
-    new_chunk->print_on(out);
-    chunk_manager()->locked_print_free_chunks(out);
+    LogStream ls(log.trace());
+    new_chunk->print_on(&ls);
+    chunk_manager()->locked_print_free_chunks(&ls);
   }
 }
 
@@ -3201,10 +3207,11 @@
 
   initialize_class_space(metaspace_rs);
 
-  if (log_is_enabled(Trace, gc, metaspace)) {
-    Log(gc, metaspace) log;
+  LogTarget(Trace, gc, metaspace) lt;
+  if (lt.is_enabled()) {
     ResourceMark rm;
-    print_compressed_class_space(log.trace_stream(), requested_addr);
+    LogStream ls(lt);
+    print_compressed_class_space(&ls, requested_addr);
   }
 }
 
@@ -3658,11 +3665,11 @@
     log.info("Metaspace (%s) allocation failed for size " SIZE_FORMAT,
              is_class_space_allocation(mdtype) ? "class" : "data", word_size);
     ResourceMark rm;
-    outputStream* out = log.info_stream();
+    LogStream ls(log.info());
     if (loader_data->metaspace_or_null() != NULL) {
-      loader_data->dump(out);
+      loader_data->dump(&ls);
     }
-    MetaspaceAux::dump(out);
+    MetaspaceAux::dump(&ls);
   }
 
   bool out_of_compressed_class_space = false;
--- a/src/share/vm/memory/universe.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/memory/universe.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -41,6 +41,7 @@
 #include "gc/shared/space.hpp"
 #include "interpreter/interpreter.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/filemap.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/metaspaceShared.hpp"
@@ -774,10 +775,11 @@
 
     Universe::set_narrow_ptrs_base(Universe::narrow_oop_base());
 
-    if (log_is_enabled(Info, gc, heap, coops)) {
+    LogTarget(Info, gc, heap, coops) lt;
+    if (lt.is_enabled()) {
       ResourceMark rm;
-      outputStream* logst = Log(gc, heap, coops)::info_stream();
-      Universe::print_compressed_oops_mode(logst);
+      LogStream ls(lt);
+      Universe::print_compressed_oops_mode(&ls);
     }
 
     // Tell tests in which mode we run.
@@ -1110,20 +1112,22 @@
 }
 
 void Universe::print_heap_before_gc() {
-  Log(gc, heap) log;
-  if (log.is_debug()) {
-    log.debug("Heap before GC invocations=%u (full %u):", heap()->total_collections(), heap()->total_full_collections());
+  LogTarget(Debug, gc, heap) lt;
+  if (lt.is_enabled()) {
+    LogStream ls(lt);
+    ls.print("Heap before GC invocations=%u (full %u):", heap()->total_collections(), heap()->total_full_collections());
     ResourceMark rm;
-    heap()->print_on(log.debug_stream());
+    heap()->print_on(&ls);
   }
 }
 
 void Universe::print_heap_after_gc() {
-  Log(gc, heap) log;
-  if (log.is_debug()) {
-    log.debug("Heap after GC invocations=%u (full %u):", heap()->total_collections(), heap()->total_full_collections());
+  LogTarget(Debug, gc, heap) lt;
+  if (lt.is_enabled()) {
+    LogStream ls(lt);
+    ls.print("Heap after GC invocations=%u (full %u):", heap()->total_collections(), heap()->total_full_collections());
     ResourceMark rm;
-    heap()->print_on(log.debug_stream());
+    heap()->print_on(&ls);
   }
 }
 
--- a/src/share/vm/oops/generateOopMap.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/oops/generateOopMap.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "interpreter/bytecodeStream.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "oops/generateOopMap.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/symbol.hpp"
@@ -1264,10 +1265,10 @@
 
 void GenerateOopMap::report_monitor_mismatch(const char *msg) {
   ResourceMark rm;
-  outputStream* out = Log(monitormismatch)::info_stream();
-  out->print("Monitor mismatch in method ");
-  method()->print_short_name(out);
-  out->print_cr(": %s", msg);
+  LogStream ls(Log(monitormismatch)::info());
+  ls.print("Monitor mismatch in method ");
+  method()->print_short_name(&ls);
+  ls.print_cr(": %s", msg);
 }
 
 void GenerateOopMap::print_states(outputStream *os,
--- a/src/share/vm/oops/instanceKlass.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/oops/instanceKlass.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -42,6 +42,7 @@
 #include "jvmtifiles/jvmti.h"
 #include "logging/log.hpp"
 #include "logging/logMessage.hpp"
+#include "logging/logStream.hpp"
 #include "memory/heapInspection.hpp"
 #include "memory/iterator.inline.hpp"
 #include "memory/metadataFactory.hpp"
@@ -1085,12 +1086,13 @@
 
   methodHandle h_method(THREAD, class_initializer());
   assert(!is_initialized(), "we cannot initialize twice");
-  if (log_is_enabled(Info, class, init)) {
+  LogTarget(Info, class, init) lt;
+  if (lt.is_enabled()) {
     ResourceMark rm;
-    outputStream* log = Log(class, init)::info_stream();
-    log->print("%d Initializing ", call_class_initializer_counter++);
-    name()->print_value_on(log);
-    log->print_cr("%s (" INTPTR_FORMAT ")", h_method() == NULL ? "(no method)" : "", p2i(this));
+    LogStream ls(lt);
+    ls.print("%d Initializing ", call_class_initializer_counter++);
+    name()->print_value_on(&ls);
+    ls.print_cr("%s (" INTPTR_FORMAT ")", h_method() == NULL ? "(no method)" : "", p2i(this));
   }
   if (h_method() != NULL) {
     JavaCallArguments args; // No arguments
--- a/src/share/vm/oops/klassVtable.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/oops/klassVtable.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -27,6 +27,7 @@
 #include "classfile/vmSymbols.hpp"
 #include "gc/shared/gcLocker.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/metaspaceShared.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.inline.hpp"
@@ -302,15 +303,16 @@
       if (supersuperklass->is_override(super_method, target_loader, target_classname, THREAD)) {
         if (log_develop_is_enabled(Trace, vtables)) {
           ResourceMark rm(THREAD);
-          outputStream* logst = Log(vtables)::trace_stream();
+          LogTarget(Trace, vtables) lt;
+          LogStream ls(lt);
           char* sig = target_method()->name_and_sig_as_C_string();
-          logst->print("transitive overriding superclass %s with %s index %d, original flags: ",
+          ls.print("transitive overriding superclass %s with %s index %d, original flags: ",
                        supersuperklass->internal_name(),
                        sig, vtable_index);
-          super_method->print_linkage_flags(logst);
-          logst->print("overriders flags: ");
-          target_method->print_linkage_flags(logst);
-          logst->cr();
+          super_method->print_linkage_flags(&ls);
+          ls.print("overriders flags: ");
+          target_method->print_linkage_flags(&ls);
+          ls.cr();
         }
 
         break; // return found superk
@@ -333,19 +335,20 @@
 #ifndef PRODUCT
   if (log_develop_is_enabled(Trace, vtables)) {
     ResourceMark rm(thread);
-    outputStream* logst = Log(vtables)::trace_stream();
+    LogTarget(Trace, vtables) lt;
+    LogStream ls(lt);
     char* sig = target_method()->name_and_sig_as_C_string();
     if (overrides) {
-      logst->print("overriding with %s index %d, original flags: ",
+      ls.print("overriding with %s index %d, original flags: ",
                    sig, i);
     } else {
-      logst->print("NOT overriding with %s index %d, original flags: ",
+      ls.print("NOT overriding with %s index %d, original flags: ",
                    sig, i);
     }
-    super_method->print_linkage_flags(logst);
-    logst->print("overriders flags: ");
-    target_method->print_linkage_flags(logst);
-    logst->cr();
+    super_method->print_linkage_flags(&ls);
+    ls.print("overriders flags: ");
+    target_method->print_linkage_flags(&ls);
+    ls.cr();
   }
 #endif
 }
@@ -551,13 +554,14 @@
   } else {
     if (log_develop_is_enabled(Trace, vtables)) {
       ResourceMark rm;
-      outputStream* logst = Log(vtables)::trace_stream();
+      LogTarget(Trace, vtables) lt;
+      LogStream ls(lt);
       const char* sig = (m != NULL) ? m->name_and_sig_as_C_string() : "<NULL>";
-      logst->print("adding %s at index %d, flags: ", sig, index);
+      ls.print("adding %s at index %d, flags: ", sig, index);
       if (m != NULL) {
-        m->print_linkage_flags(logst);
+        m->print_linkage_flags(&ls);
       }
-      logst->cr();
+      ls.cr();
     }
     table()[index].set(m);
   }
@@ -885,13 +889,14 @@
     if (log_develop_is_enabled(Trace, vtables)) {
       Method* meth = mirandas.at(i);
       ResourceMark rm(Thread::current());
-      outputStream* logst = Log(vtables)::trace_stream();
+      LogTarget(Trace, vtables) lt;
+      LogStream ls(lt);
       if (meth != NULL) {
         char* sig = meth->name_and_sig_as_C_string();
-        logst->print("fill in mirandas with %s index %d, flags: ",
+        ls.print("fill in mirandas with %s index %d, flags: ",
                      sig, initialized);
-        meth->print_linkage_flags(logst);
-        logst->cr();
+        meth->print_linkage_flags(&ls);
+        ls.cr();
       }
     }
     put_method_at(mirandas.at(i), initialized);
@@ -1117,16 +1122,17 @@
       // If m is already assigned a vtable index, do not disturb it.
       if (log_develop_is_enabled(Trace, itables)) {
         ResourceMark rm;
-        outputStream* logst = Log(itables)::trace_stream();
+        LogTarget(Trace, itables) lt;
+        LogStream ls(lt);
         assert(m != NULL, "methods can never be null");
         const char* sig = m->name_and_sig_as_C_string();
         if (m->has_vtable_index()) {
-          logst->print("vtable index %d for method: %s, flags: ", m->vtable_index(), sig);
+          ls.print("vtable index %d for method: %s, flags: ", m->vtable_index(), sig);
         } else {
-          logst->print("itable index %d for method: %s, flags: ", ime_num, sig);
+          ls.print("itable index %d for method: %s, flags: ", ime_num, sig);
         }
-        m->print_linkage_flags(logst);
-        logst->cr();
+        m->print_linkage_flags(&ls);
+        ls.cr();
       }
       if (!m->has_vtable_index()) {
         // A shared method could have an initialized itable_index that
@@ -1237,14 +1243,15 @@
       if (log_develop_is_enabled(Trace, itables)) {
         ResourceMark rm(THREAD);
         if (target() != NULL) {
-          outputStream* logst = Log(itables)::trace_stream();
+          LogTarget(Trace, itables) lt;
+          LogStream ls(lt);
           char* sig = target()->name_and_sig_as_C_string();
-          logst->print("interface: %s, ime_num: %d, target: %s, method_holder: %s ",
+          ls.print("interface: %s, ime_num: %d, target: %s, method_holder: %s ",
                        interf->internal_name(), ime_num, sig,
                        target()->method_holder()->internal_name());
-          logst->print("target_method flags: ");
-          target()->print_linkage_flags(logst);
-          logst->cr();
+          ls.print("target_method flags: ");
+          target()->print_linkage_flags(&ls);
+          ls.cr();
         }
       }
     }
--- a/src/share/vm/opto/runtime.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/opto/runtime.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -43,6 +43,7 @@
 #include "interpreter/interpreter.hpp"
 #include "interpreter/linkResolver.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/objArrayKlass.hpp"
@@ -1287,9 +1288,11 @@
   // normal bytecode execution.
   thread->clear_exception_oop_and_pc();
 
-  if (log_is_enabled(Info, exceptions)) {
+  LogTarget(Info, exceptions) lt;
+  if (lt.is_enabled()) {
     ResourceMark rm;
-    trace_exception(Log(exceptions)::info_stream(), exception(), pc, "");
+    LogStream ls(lt);
+    trace_exception(&ls, exception(), pc, "");
   }
 
   // for AbortVMOnException flag
--- a/src/share/vm/prims/jvmtiExport.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/prims/jvmtiExport.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -416,7 +416,7 @@
 
   if (HAS_PENDING_EXCEPTION) {
     LogTarget(Trace, jvmti) log;
-    LogStreamCHeap log_stream(log);
+    LogStream log_stream(log);
     java_lang_Throwable::print(PENDING_EXCEPTION, &log_stream);
     log_stream.cr();
     CLEAR_PENDING_EXCEPTION;
@@ -444,7 +444,7 @@
 
   if (HAS_PENDING_EXCEPTION) {
     LogTarget(Trace, jvmti) log;
-    LogStreamCHeap log_stream(log);
+    LogStream log_stream(log);
     java_lang_Throwable::print(PENDING_EXCEPTION, &log_stream);
     log_stream.cr();
     CLEAR_PENDING_EXCEPTION;
@@ -476,7 +476,7 @@
   if (HAS_PENDING_EXCEPTION) {
     Symbol* ex_name = PENDING_EXCEPTION->klass()->name();
     LogTarget(Trace, jvmti) log;
-    LogStreamCHeap log_stream(log);
+    LogStream log_stream(log);
     java_lang_Throwable::print(PENDING_EXCEPTION, &log_stream);
     log_stream.cr();
     CLEAR_PENDING_EXCEPTION;
@@ -511,7 +511,7 @@
   if (HAS_PENDING_EXCEPTION) {
     Symbol* ex_name = PENDING_EXCEPTION->klass()->name();
     LogTarget(Trace, jvmti) log;
-    LogStreamCHeap log_stream(log);
+    LogStream log_stream(log);
     java_lang_Throwable::print(PENDING_EXCEPTION, &log_stream);
     log_stream.cr();
     CLEAR_PENDING_EXCEPTION;
@@ -543,7 +543,7 @@
 
   if (HAS_PENDING_EXCEPTION) {
     LogTarget(Trace, jvmti) log;
-    LogStreamCHeap log_stream(log);
+    LogStream log_stream(log);
     java_lang_Throwable::print(PENDING_EXCEPTION, &log_stream);
     log_stream.cr();
     CLEAR_PENDING_EXCEPTION;
@@ -574,7 +574,7 @@
 
   if (HAS_PENDING_EXCEPTION) {
     LogTarget(Trace, jvmti) log;
-    LogStreamCHeap log_stream(log);
+    LogStream log_stream(log);
     java_lang_Throwable::print(PENDING_EXCEPTION, &log_stream);
     log_stream.cr();
     CLEAR_PENDING_EXCEPTION;
--- a/src/share/vm/prims/jvmtiImpl.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/prims/jvmtiImpl.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -393,7 +393,7 @@
 void JvmtiBreakpoints::print() {
 #ifndef PRODUCT
   LogTarget(Trace, jvmti) log;
-  LogStreamCHeap log_stream(log);
+  LogStream log_stream(log);
 
   int n = _bps.length();
   for (int i=0; i<n; i++) {
--- a/src/share/vm/prims/stackwalk.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/prims/stackwalk.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -27,6 +27,7 @@
 #include "classfile/javaClasses.inline.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/oopFactory.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/objArrayOop.inline.hpp"
@@ -121,24 +122,26 @@
     // not set) and when StackWalker::getCallerClass is called
     if (!ShowHiddenFrames && (skip_hidden_frames(mode) || get_caller_class(mode))) {
       if (method->is_hidden()) {
-        if (log_is_enabled(Debug, stackwalk)) {
+        LogTarget(Debug, stackwalk) lt;
+        if (lt.is_enabled()) {
           ResourceMark rm(THREAD);
-          outputStream* st = Log(stackwalk)::debug_stream();
-          st->print("  hidden method: ");
-          method->print_short_name(st);
-          st->cr();
+          LogStream ls(lt);
+          ls.print("  hidden method: ");
+          method->print_short_name(&ls);
+          ls.cr();
         }
         continue;
       }
     }
 
     int index = end_index++;
-    if (log_is_enabled(Debug, stackwalk)) {
+    LogTarget(Debug, stackwalk) lt;
+    if (lt.is_enabled()) {
       ResourceMark rm(THREAD);
-      outputStream* st = Log(stackwalk)::debug_stream();
-      st->print("  %d: frame method: ", index);
-      method->print_short_name(st);
-      st->print_cr(" bci=%d", stream.bci());
+      LogStream ls(lt);
+      ls.print("  %d: frame method: ", index);
+      method->print_short_name(&ls);
+      ls.print_cr(" bci=%d", stream.bci());
     }
 
     if (!need_method_info(mode) && get_caller_class(mode) &&
@@ -364,12 +367,13 @@
         break;
       }
 
-      if (log_is_enabled(Debug, stackwalk)) {
+      LogTarget(Debug, stackwalk) lt;
+      if (lt.is_enabled()) {
         ResourceMark rm(THREAD);
-        outputStream* st = Log(stackwalk)::debug_stream();
-        st->print("  skip ");
-        stream.method()->print_short_name(st);
-        st->cr();
+        LogStream ls(lt);
+        ls.print("  skip ");
+        stream.method()->print_short_name(&ls);
+        ls.cr();
       }
       stream.next();
     }
@@ -377,12 +381,13 @@
     // stack frame has been traversed individually and resume stack walk
     // from the stack frame at depth == skip_frames.
     for (int n=0; n < skip_frames && !stream.at_end(); stream.next(), n++) {
-      if (log_is_enabled(Debug, stackwalk)) {
+      LogTarget(Debug, stackwalk) lt;
+      if (lt.is_enabled()) {
         ResourceMark rm(THREAD);
-        outputStream* st = Log(stackwalk)::debug_stream();
-        st->print("  skip ");
-        stream.method()->print_short_name(st);
-        st->cr();
+        LogStream ls(lt);
+        ls.print("  skip ");
+        stream.method()->print_short_name(&ls);
+        ls.cr();
       }
     }
   }
--- a/src/share/vm/runtime/arguments.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/runtime/arguments.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -4265,7 +4265,7 @@
     const char* gc_conf = PrintGCDetails ? "gc*" : "gc";
 
     LogTarget(Error, logging) target;
-    LogStreamCHeap errstream(target);
+    LogStream errstream(target);
     return LogConfiguration::parse_log_arguments(_gc_log_filename, gc_conf, NULL, NULL, &errstream);
   } else if (PrintGC || PrintGCDetails) {
     LogConfiguration::configure_stdout(LogLevel::Info, !PrintGCDetails, LOG_TAGS(gc));
--- a/src/share/vm/runtime/java.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/runtime/java.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -37,6 +37,7 @@
 #include "jvmci/jvmciRuntime.hpp"
 #endif
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.hpp"
@@ -481,9 +482,11 @@
   Log(gc, heap, exit) log;
   if (log.is_info()) {
     ResourceMark rm;
-    Universe::print_on(log.info_stream());
+    LogStream ls_info(log.info());
+    Universe::print_on(&ls_info);
     if (log.is_trace()) {
-      ClassLoaderDataGraph::dump_on(log.trace_stream());
+      LogStream ls_trace(log.trace());
+      ClassLoaderDataGraph::dump_on(&ls_trace);
     }
   }
 
--- a/src/share/vm/runtime/os.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/runtime/os.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -34,7 +34,7 @@
 #include "gc/shared/vmGCOperations.hpp"
 #include "interpreter/interpreter.hpp"
 #include "logging/log.hpp"
-#include "logging/logStream.inline.hpp"
+#include "logging/logStream.hpp"
 #include "memory/allocation.inline.hpp"
 #ifdef ASSERT
 #include "memory/guardedMemory.hpp"
@@ -1480,7 +1480,7 @@
 void os::trace_page_sizes(const char* str, const size_t* page_sizes, int count) {
   LogTarget(Info, pagesize) log;
   if (log.is_enabled()) {
-    LogStreamCHeap out(log);
+    LogStream out(log);
 
     out.print("%s: ", str);
     for (int i = 0; i < count; ++i) {
--- a/src/share/vm/runtime/safepoint.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/runtime/safepoint.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -35,6 +35,7 @@
 #include "gc/shared/gcLocker.inline.hpp"
 #include "interpreter/interpreter.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.inline.hpp"
 #include "oops/oop.inline.hpp"
@@ -226,9 +227,11 @@
             //   steps = MIN(steps, 2000-100)
             //   if (iterations != 0) steps -= NNN
           }
-          if (log_is_enabled(Trace, safepoint)) {
+          LogTarget(Trace, safepoint) lt;
+          if (lt.is_enabled()) {
             ResourceMark rm;
-            cur_state->print_on(Log(safepoint)::trace_stream());
+            LogStream ls(lt);
+            cur_state->print_on(&ls);
           }
         }
       }
--- a/src/share/vm/runtime/sweeper.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/runtime/sweeper.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -28,6 +28,8 @@
 #include "code/icBuffer.hpp"
 #include "code/nmethod.hpp"
 #include "compiler/compileBroker.hpp"
+#include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/method.hpp"
 #include "runtime/atomic.hpp"
@@ -504,7 +506,8 @@
 
   Log(codecache, sweep) log;
   if (log.is_debug()) {
-    CodeCache::print_summary(log.debug_stream(), false);
+    LogStream ls(log.debug());
+    CodeCache::print_summary(&ls, false);
   }
   log_sweep("finished");
 
--- a/src/share/vm/runtime/thread.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/runtime/thread.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -41,6 +41,7 @@
 #include "jvmtifiles/jvmtiEnv.hpp"
 #include "logging/log.hpp"
 #include "logging/logConfiguration.hpp"
+#include "logging/logStream.hpp"
 #include "memory/metaspaceShared.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/resourceArea.hpp"
@@ -111,6 +112,7 @@
 #if INCLUDE_JVMCI
 #include "jvmci/jvmciCompiler.hpp"
 #include "jvmci/jvmciRuntime.hpp"
+#include "logging/logHandle.hpp"
 #endif
 #ifdef COMPILER1
 #include "c1/c1_Compiler.hpp"
@@ -2103,15 +2105,16 @@
       // We cannot call Exceptions::_throw(...) here because we cannot block
       set_pending_exception(_pending_async_exception, __FILE__, __LINE__);
 
-      if (log_is_enabled(Info, exceptions)) {
+      LogTarget(Info, exceptions) lt;
+      if (lt.is_enabled()) {
         ResourceMark rm;
-        outputStream* logstream = Log(exceptions)::info_stream();
-        logstream->print("Async. exception installed at runtime exit (" INTPTR_FORMAT ")", p2i(this));
+        LogStream ls(lt);
+        ls.print("Async. exception installed at runtime exit (" INTPTR_FORMAT ")", p2i(this));
           if (has_last_Java_frame()) {
             frame f = last_frame();
-           logstream->print(" (pc: " INTPTR_FORMAT " sp: " INTPTR_FORMAT " )", p2i(f.pc()), p2i(f.sp()));
+           ls.print(" (pc: " INTPTR_FORMAT " sp: " INTPTR_FORMAT " )", p2i(f.pc()), p2i(f.sp()));
           }
-        logstream->print_cr(" of type: %s", _pending_async_exception->klass()->external_name());
+        ls.print_cr(" of type: %s", _pending_async_exception->klass()->external_name());
       }
       _pending_async_exception = NULL;
       clear_has_async_exception();
--- a/src/share/vm/runtime/vm_operations.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/runtime/vm_operations.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -29,6 +29,7 @@
 #include "compiler/compileBroker.hpp"
 #include "gc/shared/isGCActiveMark.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/heapInspection.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/symbol.hpp"
@@ -55,19 +56,19 @@
 
 void VM_Operation::evaluate() {
   ResourceMark rm;
-  outputStream* debugstream;
-  bool enabled = log_is_enabled(Debug, vmoperation);
-  if (enabled) {
-    debugstream = Log(vmoperation)::debug_stream();
-    debugstream->print("begin ");
-    print_on_error(debugstream);
-    debugstream->cr();
+  LogTarget(Debug, vmoperation) lt;
+  if (lt.is_enabled()) {
+    LogStream ls(lt);
+    ls.print("begin ");
+    print_on_error(&ls);
+    ls.cr();
   }
   doit();
-  if (enabled) {
-    debugstream->print("end ");
-    print_on_error(debugstream);
-    debugstream->cr();
+  if (lt.is_enabled()) {
+    LogStream ls(lt);
+    ls.print("end ");
+    print_on_error(&ls);
+    ls.cr();
   }
 }
 
--- a/src/share/vm/runtime/vm_version.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/runtime/vm_version.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/universe.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/arguments.hpp"
@@ -299,8 +300,8 @@
   if (log_is_enabled(Info, os, cpu)) {
     char buf[1024];
     ResourceMark rm;
-    outputStream* log = Log(os, cpu)::info_stream();
-    os::print_cpu_info(log, buf, sizeof(buf));
+    LogStream ls(Log(os, cpu)::info());
+    os::print_cpu_info(&ls, buf, sizeof(buf));
   }
 }
 
--- a/src/share/vm/utilities/exceptions.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/src/share/vm/utilities/exceptions.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -27,6 +27,7 @@
 #include "classfile/vmSymbols.hpp"
 #include "compiler/compileBroker.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/init.hpp"
@@ -53,11 +54,12 @@
 }
 
 void ThreadShadow::clear_pending_exception() {
-  if (_pending_exception != NULL && log_is_enabled(Debug, exceptions)) {
+  LogTarget(Debug, exceptions) lt;
+  if (_pending_exception != NULL && lt.is_enabled()) {
     ResourceMark rm;
-    outputStream* logst = Log(exceptions)::debug_stream();
-    logst->print("Thread::clear_pending_exception: cleared exception:");
-    _pending_exception->print_on(logst);
+    LogStream ls(lt);
+    ls.print("Thread::clear_pending_exception: cleared exception:");
+    _pending_exception->print_on(&ls);
   }
   _pending_exception = NULL;
   _exception_file    = NULL;
--- a/test/native/logging/test_logConfiguration.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/test/native/logging/test_logConfiguration.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -363,7 +363,8 @@
 
   LogConfiguration::register_update_listener(&Test_logconfiguration_subscribe_helper);
 
-  LogConfiguration::parse_log_arguments("stdout", "logging=trace", NULL, NULL, log.error_stream());
+  LogStream ls(log.error());
+  LogConfiguration::parse_log_arguments("stdout", "logging=trace", NULL, NULL, &ls);
   ASSERT_EQ(1, Test_logconfiguration_subscribe_triggered);
 
   LogConfiguration::configure_stdout(LogLevel::Debug, true, LOG_TAGS(gc));
--- a/test/native/logging/test_logStream.cpp	Thu Jul 20 17:23:24 2017 -0700
+++ b/test/native/logging/test_logStream.cpp	Fri Jul 21 09:50:12 2017 +0200
@@ -63,21 +63,40 @@
 
 TEST_VM_F(LogStreamTest, no_rm) {
   ResourceMark rm;
-  outputStream* stream = LogTarget(Debug, gc)::stream();
-
-  verify_stream(stream);
+  LogStream ls(Log(gc)::debug());
+  verify_stream(&ls);
 }
 
-TEST_VM_F(LogStreamTest, c_heap_stream) {
-  Log(gc) log;
-  LogStreamCHeap stream(log.debug());
-
-  verify_stream(&stream);
+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.buffer();
+      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().
+  }
 }
 
-TEST_VM_F(LogStreamTest, c_heap_stream_target) {
-  LogTarget(Debug, gc) log;
-  LogStreamCHeap stream(log);
-
-  verify_stream(&stream);
+// Test, in release build, that the internal line buffer of a LogStream
+// object caps out at 1M.
+TEST_VM_F(LogStreamTest, TestLineBufferAllocationCap) {
+  LogStream ls(Log(logging)::info());
+  for (size_t i = 0; i < (1*M + 512); i ++) {
+    ls.print_raw("A");
+  }
+  const char* const line_buffer = ls._current_line.buffer();
+  ASSERT_TRUE(strlen(line_buffer) == 1*M - 1);
+  // reset to prevent assert for unflushed content
+  ls._current_line.reset();
 }