changeset 60054:968ee9178447

Merge
author psadhukhan
date Fri, 03 Jul 2020 18:58:03 +0530
parents 6be09b0e84e6 a7c030723240
children 47ae69ddb234
files
diffstat 21 files changed, 543 insertions(+), 64 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/c1/c1_Compilation.cpp	Fri Jul 03 09:26:16 2020 +0530
+++ b/src/hotspot/share/c1/c1_Compilation.cpp	Fri Jul 03 18:58:03 2020 +0530
@@ -463,7 +463,7 @@
   // Note: make sure we mark the method as not compilable!
   CHECK_BAILOUT();
 
-  if (InstallMethods) {
+  if (should_install_code()) {
     // install code
     PhaseTraceTime timeit(_t_codeinstall);
     install_code(frame_size);
@@ -539,7 +539,7 @@
 }
 
 Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method,
-                         int osr_bci, BufferBlob* buffer_blob, DirectiveSet* directive)
+                         int osr_bci, BufferBlob* buffer_blob, bool install_code, DirectiveSet* directive)
 : _next_id(0)
 , _next_block_id(0)
 , _compiler(compiler)
@@ -558,6 +558,7 @@
 , _would_profile(false)
 , _has_method_handle_invokes(false)
 , _has_reserved_stack_access(method->has_reserved_stack_access())
+, _install_code(install_code)
 , _bailout_msg(NULL)
 , _exception_info_list(NULL)
 , _allocator(NULL)
--- a/src/hotspot/share/c1/c1_Compilation.hpp	Fri Jul 03 09:26:16 2020 +0530
+++ b/src/hotspot/share/c1/c1_Compilation.hpp	Fri Jul 03 18:58:03 2020 +0530
@@ -81,6 +81,7 @@
   bool               _would_profile;
   bool               _has_method_handle_invokes;  // True if this method has MethodHandle invokes.
   bool               _has_reserved_stack_access;
+  bool               _install_code;
   const char*        _bailout_msg;
   ExceptionInfoList* _exception_info_list;
   ExceptionHandlerTable _exception_handler_table;
@@ -120,7 +121,7 @@
  public:
   // creation
   Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method,
-              int osr_bci, BufferBlob* buffer_blob, DirectiveSet* directive);
+              int osr_bci, BufferBlob* buffer_blob, bool install_code, DirectiveSet* directive);
   ~Compilation();
 
 
@@ -148,6 +149,7 @@
   CodeOffsets* offsets()                         { return &_offsets; }
   Arena* arena()                                 { return _arena; }
   bool has_access_indexed()                      { return _has_access_indexed; }
+  bool should_install_code()                     { return _install_code && InstallMethods; }
 
   // Instruction ids
   int get_next_id()                              { return _next_id++; }
--- a/src/hotspot/share/c1/c1_Compiler.cpp	Fri Jul 03 09:26:16 2020 +0530
+++ b/src/hotspot/share/c1/c1_Compiler.cpp	Fri Jul 03 18:58:03 2020 +0530
@@ -235,7 +235,7 @@
   return true;
 }
 
-void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci, DirectiveSet* directive) {
+void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci, bool install_code, DirectiveSet* directive) {
   BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
   assert(buffer_blob != NULL, "Must exist");
   // invoke compilation
@@ -244,7 +244,7 @@
     // of Compilation to occur before we release the any
     // competing compiler thread
     ResourceMark rm;
-    Compilation c(this, env, method, entry_bci, buffer_blob, directive);
+    Compilation c(this, env, method, entry_bci, buffer_blob, install_code, directive);
   }
 }
 
--- a/src/hotspot/share/c1/c1_Compiler.hpp	Fri Jul 03 09:26:16 2020 +0530
+++ b/src/hotspot/share/c1/c1_Compiler.hpp	Fri Jul 03 18:58:03 2020 +0530
@@ -51,7 +51,7 @@
   virtual void initialize();
 
   // Compilation entry point for methods
-  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive);
+  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, bool install_code, DirectiveSet* directive);
 
   // Print compilation timers and statistics
   virtual void print_timers();
--- a/src/hotspot/share/compiler/abstractCompiler.hpp	Fri Jul 03 09:26:16 2020 +0530
+++ b/src/hotspot/share/compiler/abstractCompiler.hpp	Fri Jul 03 18:58:03 2020 +0530
@@ -166,7 +166,7 @@
   void set_state     (int state);
   void set_shut_down ()           { set_state(shut_down); }
   // Compilation entry point for methods
-  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
+  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, bool install_code, DirectiveSet* directive) {
     ShouldNotReachHere();
   }
 
--- a/src/hotspot/share/compiler/compileBroker.cpp	Fri Jul 03 09:26:16 2020 +0530
+++ b/src/hotspot/share/compiler/compileBroker.cpp	Fri Jul 03 18:58:03 2020 +0530
@@ -2223,7 +2223,15 @@
           locker.wait();
         }
       }
-      comp->compile_method(&ci_env, target, osr_bci, directive);
+      comp->compile_method(&ci_env, target, osr_bci, true, directive);
+
+      /* Repeat compilation without installing code for profiling purposes */
+      int repeat_compilation_count = directive->RepeatCompilationOption;
+      while (repeat_compilation_count > 0) {
+        task->print_ul("NO CODE INSTALLED");
+        comp->compile_method(&ci_env, target, osr_bci, false , directive);
+        repeat_compilation_count--;
+      }
     }
 
     if (!ci_env.failing() && task->code() == NULL) {
--- a/src/hotspot/share/compiler/compilerDirectives.hpp	Fri Jul 03 09:26:16 2020 +0530
+++ b/src/hotspot/share/compiler/compilerDirectives.hpp	Fri Jul 03 18:58:03 2020 +0530
@@ -48,7 +48,8 @@
     cflags(DumpInline,              bool, false, DumpInline) \
     cflags(CompilerDirectivesIgnoreCompileCommands, bool, CompilerDirectivesIgnoreCompileCommands, X) \
     cflags(DisableIntrinsic,        ccstrlist, DisableIntrinsic, DisableIntrinsic) \
-    cflags(ControlIntrinsic,        ccstrlist, ControlIntrinsic, ControlIntrinsic)
+    cflags(ControlIntrinsic,        ccstrlist, ControlIntrinsic, ControlIntrinsic) \
+    cflags(RepeatCompilation,       intx, RepeatCompilation, RepeatCompilation)
 
 #ifdef COMPILER1
   #define compilerdirectives_c1_flags(cflags)
@@ -64,11 +65,11 @@
 NOT_PRODUCT(cflags(TraceOptoPipelining, bool, TraceOptoPipelining, TraceOptoPipelining)) \
 NOT_PRODUCT(cflags(TraceOptoOutput,     bool, TraceOptoOutput, TraceOptoOutput)) \
 NOT_PRODUCT(cflags(PrintIdeal,          bool, PrintIdeal, PrintIdeal)) \
-NOT_PRODUCT(cflags(IGVPrintLevel,       intx, PrintIdealGraphLevel, IGVPrintLevel)) \
     cflags(TraceSpilling,           bool, TraceSpilling, TraceSpilling) \
     cflags(Vectorize,               bool, false, Vectorize) \
+    cflags(CloneMapDebug,           bool, false, CloneMapDebug) \
+NOT_PRODUCT(cflags(IGVPrintLevel,       intx, PrintIdealGraphLevel, IGVPrintLevel)) \
     cflags(VectorizeDebug,          uintx, 0, VectorizeDebug) \
-    cflags(CloneMapDebug,           bool, false, CloneMapDebug) \
     cflags(MaxNodeLimit,            intx, MaxNodeLimit, MaxNodeLimit)
 #else
   #define compilerdirectives_c2_flags(cflags)
--- a/src/hotspot/share/jvmci/jvmciCompiler.cpp	Fri Jul 03 09:26:16 2020 +0530
+++ b/src/hotspot/share/jvmci/jvmciCompiler.cpp	Fri Jul 03 18:58:03 2020 +0530
@@ -135,7 +135,7 @@
 }
 
 // Compilation entry point for methods
-void JVMCICompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
+void JVMCICompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, bool install_code, DirectiveSet* directive) {
   ShouldNotReachHere();
 }
 
--- a/src/hotspot/share/jvmci/jvmciCompiler.hpp	Fri Jul 03 09:26:16 2020 +0530
+++ b/src/hotspot/share/jvmci/jvmciCompiler.hpp	Fri Jul 03 18:58:03 2020 +0530
@@ -94,7 +94,7 @@
   }
 
   // Compilation entry point for methods
-  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive);
+  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, bool install_code, DirectiveSet* directive);
 
   // Print compilation timers and statistics
   virtual void print_timers();
--- a/src/hotspot/share/opto/c2compiler.cpp	Fri Jul 03 09:26:16 2020 +0530
+++ b/src/hotspot/share/opto/c2compiler.cpp	Fri Jul 03 18:58:03 2020 +0530
@@ -99,7 +99,7 @@
   }
 }
 
-void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
+void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, bool install_code, DirectiveSet* directive) {
   assert(is_initialized(), "Compiler thread must be initialized");
 
   bool subsume_loads = SubsumeLoads;
@@ -109,7 +109,7 @@
 
   while (!env->failing()) {
     // Attempt to compile while subsuming loads into machine instructions.
-    Compile C(env, target, entry_bci, subsume_loads, do_escape_analysis, eliminate_boxing, directive);
+    Compile C(env, target, entry_bci, subsume_loads, do_escape_analysis, eliminate_boxing, install_code, directive);
 
     // Check result and retry if appropriate.
     if (C.failure_reason() != NULL) {
@@ -151,7 +151,6 @@
         continue;  // retry
       }
     }
-
     // print inlining for last compilation only
     C.dump_print_inlining();
 
--- a/src/hotspot/share/opto/c2compiler.hpp	Fri Jul 03 09:26:16 2020 +0530
+++ b/src/hotspot/share/opto/c2compiler.hpp	Fri Jul 03 18:58:03 2020 +0530
@@ -43,6 +43,7 @@
   void compile_method(ciEnv* env,
                       ciMethod* target,
                       int entry_bci,
+                      bool install_code,
                       DirectiveSet* directive);
 
   // sentinel value used to trigger backtracking in compile_method().
--- a/src/hotspot/share/opto/compile.cpp	Fri Jul 03 09:26:16 2020 +0530
+++ b/src/hotspot/share/opto/compile.cpp	Fri Jul 03 18:58:03 2020 +0530
@@ -499,12 +499,13 @@
 
 
 Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci,
-                  bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing, DirectiveSet* directive)
+                  bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing, bool install_code, DirectiveSet* directive)
                 : Phase(Compiler),
                   _compile_id(ci_env->compile_id()),
                   _save_argument_registers(false),
                   _subsume_loads(subsume_loads),
                   _do_escape_analysis(do_escape_analysis),
+                  _install_code(install_code),
                   _eliminate_boxing(eliminate_boxing),
                   _method(target),
                   _entry_bci(osr_bci),
@@ -791,6 +792,7 @@
     _save_argument_registers(save_arg_registers),
     _subsume_loads(true),
     _do_escape_analysis(false),
+    _install_code(true),
     _eliminate_boxing(false),
     _method(NULL),
     _entry_bci(InvocationEntryBci),
--- a/src/hotspot/share/opto/compile.hpp	Fri Jul 03 09:26:16 2020 +0530
+++ b/src/hotspot/share/opto/compile.hpp	Fri Jul 03 18:58:03 2020 +0530
@@ -246,6 +246,7 @@
   const bool            _save_argument_registers; // save/restore arg regs for trampolines
   const bool            _subsume_loads;         // Load can be matched as part of a larger op.
   const bool            _do_escape_analysis;    // Do escape analysis.
+  const bool            _install_code;          // Install the code that was compiled
   const bool            _eliminate_boxing;      // Do boxing elimination.
   ciMethod*             _method;                // The method being compiled.
   int                   _entry_bci;             // entry bci for osr methods.
@@ -507,7 +508,7 @@
   /** Do aggressive boxing elimination. */
   bool              aggressive_unboxing() const { return _eliminate_boxing && AggressiveUnboxing; }
   bool              save_argument_registers() const { return _save_argument_registers; }
-
+  bool              should_install_code() const { return _install_code; }
 
   // Other fixed compilation parameters.
   ciMethod*         method() const              { return _method; }
@@ -1008,7 +1009,7 @@
   // continuation.
   Compile(ciEnv* ci_env, ciMethod* target,
           int entry_bci, bool subsume_loads, bool do_escape_analysis,
-          bool eliminate_boxing, DirectiveSet* directive);
+          bool eliminate_boxing, bool install_code, DirectiveSet* directive);
 
   // Second major entry point.  From the TypeFunc signature, generate code
   // to pass arguments from the Java calling convention to the C calling
--- a/src/hotspot/share/opto/output.cpp	Fri Jul 03 09:26:16 2020 +0530
+++ b/src/hotspot/share/opto/output.cpp	Fri Jul 03 18:58:03 2020 +0530
@@ -3260,7 +3260,9 @@
 }
 
 void PhaseOutput::install() {
-  if (C->stub_function() != NULL) {
+  if (!C->should_install_code()) {
+    return;
+  } else if (C->stub_function() != NULL) {
     install_stub(C->stub_name(),
                  C->save_argument_registers());
   } else {
--- a/src/hotspot/share/runtime/globals.hpp	Fri Jul 03 09:26:16 2020 +0530
+++ b/src/hotspot/share/runtime/globals.hpp	Fri Jul 03 18:58:03 2020 +0530
@@ -538,6 +538,10 @@
   product(bool, PrintCompilation, false,                                    \
           "Print compilations")                                             \
                                                                             \
+  diagnostic(intx, RepeatCompilation, 0,                                    \
+          "Repeat compilation without installing code (number of times)")   \
+          range(0, max_jint)                                                 \
+                                                                            \
   product(bool, PrintExtendedThreadInfo, false,                             \
           "Print more information in thread dump")                          \
                                                                             \
--- a/src/java.desktop/share/classes/sun/font/SunFontManager.java	Fri Jul 03 09:26:16 2020 +0530
+++ b/src/java.desktop/share/classes/sun/font/SunFontManager.java	Fri Jul 03 18:58:03 2020 +0530
@@ -353,6 +353,9 @@
 
                 String[] fontInfo = getDefaultPlatformFont();
                 defaultFontName = fontInfo[0];
+                if (defaultFontName == null && FontUtilities.debugFonts()) {
+                    FontUtilities.getLogger().warning("defaultFontName is null");
+                }
                 defaultFontFileName = fontInfo[1];
 
                 String extraFontPath = fontConfig.getExtraFontPath();
@@ -1888,6 +1891,7 @@
      * may be able to emulate the required style.
      */
     public Font2D findFont2D(String name, int style, int fallback) {
+        if (name == null) return null;
         String lowerCaseName = name.toLowerCase(Locale.ENGLISH);
         String mapName = lowerCaseName + dotStyleStr(style);
 
--- a/src/java.desktop/unix/classes/sun/awt/FcFontManager.java	Fri Jul 03 09:26:16 2020 +0530
+++ b/src/java.desktop/unix/classes/sun/awt/FcFontManager.java	Fri Jul 03 18:58:03 2020 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2020, 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
@@ -89,7 +89,8 @@
          */
         if (info[0] == null) {
             if (fontConfigFonts != null && fontConfigFonts.length > 0 &&
-                fontConfigFonts[0].firstFont.fontFile != null) {
+                fontConfigFonts[0].firstFont.fontFile != null &&
+                fontConfigFonts[0].firstFont.fullName != null) {
                 info[0] = fontConfigFonts[0].firstFont.fullName;
                 info[1] = fontConfigFonts[0].firstFont.fontFile;
             } else {
--- a/src/java.logging/share/classes/java/util/logging/LogRecord.java	Fri Jul 03 09:26:16 2020 +0530
+++ b/src/java.logging/share/classes/java/util/logging/LogRecord.java	Fri Jul 03 18:58:03 2020 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2020, 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
@@ -26,7 +26,6 @@
 package java.util.logging;
 import java.time.Instant;
 import java.util.*;
-import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 import java.io.*;
 import java.security.AccessController;
@@ -76,21 +75,6 @@
         = new AtomicLong(0);
 
     /**
-     * The default value of threadID will be the current thread's
-     * thread id, for ease of correlation, unless it is greater than
-     * MIN_SEQUENTIAL_THREAD_ID, in which case we try harder to keep
-     * our promise to keep threadIDs unique by avoiding collisions due
-     * to 32-bit wraparound.  Unfortunately, LogRecord.getThreadID()
-     * returns int, while Thread.getId() returns long.
-     */
-    private static final int MIN_SEQUENTIAL_THREAD_ID = Integer.MAX_VALUE / 2;
-
-    private static final AtomicInteger nextThreadId
-        = new AtomicInteger(MIN_SEQUENTIAL_THREAD_ID);
-
-    private static final ThreadLocal<Integer> threadIds = new ThreadLocal<>();
-
-    /**
      * Logging message level
      */
     private Level level;
@@ -121,6 +105,11 @@
     private int threadID;
 
     /**
+     * long value of Thread ID for thread that issued logging call.
+     */
+    private long longThreadID;
+
+    /**
      * The Throwable (if any) associated with log message
      */
     private Throwable thrown;
@@ -147,7 +136,10 @@
      * @serialField sourceClassName String Class that issued logging call
      * @serialField sourceMethodName String Method that issued logging call
      * @serialField message String Non-localized raw message text
-     * @serialField threadID int Thread ID for thread that issued logging call
+     * @serialField threadID int this is deprecated and is available for backward compatibility.
+     *              Values may have been synthesized. If present, {@code longThreadID} represents
+     *              the actual thread id.
+     * @serialField longThreadID long Thread ID for thread that issued logging call
      * @serialField millis long Truncated event time in milliseconds since 1970
      *              - calculated as getInstant().toEpochMilli().
      *               The event time instant can be reconstructed using
@@ -164,6 +156,7 @@
      * @serialField resourceBundleName String Resource bundle name to localized
      *              log message
      */
+    @Serial
     private static final ObjectStreamField[] serialPersistentFields =
         new ObjectStreamField[] {
             new ObjectStreamField("level", Level.class),
@@ -172,6 +165,7 @@
             new ObjectStreamField("sourceMethodName", String.class),
             new ObjectStreamField("message", String.class),
             new ObjectStreamField("threadID", int.class),
+            new ObjectStreamField("longThreadID", long.class),
             new ObjectStreamField("millis", long.class),
             new ObjectStreamField("nanoAdjustment", int.class),
             new ObjectStreamField("thrown", Throwable.class),
@@ -184,20 +178,22 @@
     private transient ResourceBundle resourceBundle;
 
     /**
-     * Returns the default value for a new LogRecord's threadID.
+     * Synthesizes a pseudo unique integer value from a long {@code id} value.
+     * For backward compatibility with previous releases,the returned integer is
+     * such that for any positive long less than or equals to {@code Integer.MAX_VALUE},
+     * the returned integer is equal to the original value.
+     * Otherwise - it is synthesized with a best effort hashing algorithm,
+     * and the returned value is negative.
+     * Calling this method multiple times with the same value always yields the same result.
+     *
+     * @return thread id
      */
-    private int defaultThreadID() {
-        long tid = Thread.currentThread().getId();
-        if (tid < MIN_SEQUENTIAL_THREAD_ID) {
-            return (int) tid;
-        } else {
-            Integer id = threadIds.get();
-            if (id == null) {
-                id = nextThreadId.getAndIncrement();
-                threadIds.set(id);
-            }
-            return id;
-        }
+
+    private int shortThreadID(long id) {
+        if (id >= 0 && id <= Integer.MAX_VALUE)
+            return (int) id;
+        int hash = Long.hashCode(id);
+        return hash < 0 ? hash : (-1 - hash);
     }
 
     /**
@@ -225,10 +221,13 @@
         message = msg;
         // Assign a thread ID and a unique sequence number.
         sequenceNumber = globalSequenceNumber.getAndIncrement();
-        threadID = defaultThreadID();
+        long id = Thread.currentThread().getId();
+        // threadID is deprecated and this value is synthesised for backward compatibility
+        threadID = shortThreadID(id);
+        longThreadID = id;
         instant = Instant.now();
         needToInferCaller = true;
-   }
+    }
 
     /**
      * Get the source Logger's name.
@@ -447,8 +446,12 @@
      * This is a thread identifier within the Java VM and may or
      * may not map to any operating system ID.
      *
+     * @deprecated  Values returned by this method may be synthesized,
+     *              and may not correspond to the actual {@linkplain Thread#getId() thread id},
+     *              use {@link #getLongThreadID()} instead.
      * @return thread ID
      */
+    @Deprecated(since = "16")
     public int getThreadID() {
         return threadID;
     }
@@ -456,9 +459,41 @@
     /**
      * Set an identifier for the thread where the message originated.
      * @param threadID  the thread ID
+     *
+     * @deprecated  This method doesn't allow to pass a long {@linkplain Thread#getId() thread id},
+     *              use {@link #setLongThreadID(long)} instead.
      */
+    @Deprecated(since = "16")
     public void setThreadID(int threadID) {
         this.threadID = threadID;
+        this.longThreadID = threadID;
+    }
+
+    /**
+     * Get a thread identifier for the thread where message originated
+     *
+     * <p>
+     * This is a thread identifier within the Java VM and may or
+     * may not map to any operating system ID.
+     *
+     * @return thread ID
+     * @since 16
+     */
+    public long getLongThreadID() {
+        return longThreadID;
+    }
+
+    /**
+     * Set an identifier for the thread where the message originated.
+     *
+     * @param longThreadID the thread ID
+     * @return this LogRecord
+     * @since 16
+     */
+    public LogRecord setLongThreadID(long longThreadID) {
+        this.threadID = shortThreadID(longThreadID);
+        this.longThreadID = longThreadID;
+        return this;
     }
 
     /**
@@ -552,6 +587,7 @@
         this.thrown = thrown;
     }
 
+    @Serial
     private static final long serialVersionUID = 5372048053134512534L;
 
     /**
@@ -564,6 +600,7 @@
      * a null String is written.  Otherwise the output of Object.toString()
      * is written.
      */
+    @Serial
     private void writeObject(ObjectOutputStream out) throws IOException {
         // We have to write serialized fields first.
         ObjectOutputStream.PutField pf = out.putFields();
@@ -573,6 +610,7 @@
         pf.put("sourceMethodName", sourceMethodName);
         pf.put("message", message);
         pf.put("threadID", threadID);
+        pf.put("longThreadID", longThreadID);
         pf.put("millis", instant.toEpochMilli());
         pf.put("nanoAdjustment", instant.getNano() % 1000_000);
         pf.put("thrown", thrown);
@@ -594,8 +632,25 @@
         }
     }
 
+    /**
+     * Initializes the LogRecord from deserialized data.
+     * <ul>
+     * <li>If {@code longThreadID} is present in the serial form, its value
+     * takes precedence over {@code threadID} and a value for {@code threadID}
+     * is synthesized from it, such that for {@code longThreadID} values between
+     * {@code 0} and {@code Integer.MAX_VALUE} inclusive, {@code longThreadID}
+     * and {@code threadID} will have the same value. For values outside of this
+     * range a negative synthesized value will be deterministically derived
+     * from {@code longThreadID}.
+     * <li>Otherwise, when only {@code threadID} is
+     * present, {@code longThreadID} is initialized with the value of
+     * {@code threadID} which may be anything between {@code Integer.MIN_VALUE}
+     * and {Integer.MAX_VALUE}.
+     * </ul>
+     */
+    @Serial
     private void readObject(ObjectInputStream in)
-                        throws IOException, ClassNotFoundException {
+        throws IOException, ClassNotFoundException {
         // We have to read serialized fields first.
         ObjectInputStream.GetField gf = in.readFields();
         level = (Level) gf.get("level", null);
@@ -603,7 +658,14 @@
         sourceClassName = (String) gf.get("sourceClassName", null);
         sourceMethodName = (String) gf.get("sourceMethodName", null);
         message = (String) gf.get("message", null);
-        threadID = gf.get("threadID", 0);
+        // If longthreadID is not present, it will be initialised with threadID value
+        // If longthreadID is present, threadID might have a synthesized value
+        int threadID = gf.get("threadID", 0);
+        long longThreadID = gf.get("longThreadID", (long)threadID);
+        if (threadID != longThreadID)
+            threadID = shortThreadID(longThreadID);
+        this.threadID = threadID;
+        this.longThreadID = longThreadID;
         long millis = gf.get("millis", 0L);
         int nanoOfMilli = gf.get("nanoAdjustment", 0);
         instant = Instant.ofEpochSecond(
@@ -641,9 +703,9 @@
                 // use system class loader to ensure the ResourceBundle
                 // instance is a different instance than null loader uses
                 final ResourceBundle bundle =
-                        ResourceBundle.getBundle(resourceBundleName,
-                                Locale.getDefault(),
-                                ClassLoader.getSystemClassLoader());
+                    ResourceBundle.getBundle(resourceBundleName,
+                        Locale.getDefault(),
+                        ClassLoader.getSystemClassLoader());
                 resourceBundle = bundle;
             } catch (MissingResourceException ex) {
                 // This is not a good place to throw an exception,
@@ -697,7 +759,7 @@
         private static final StackWalker WALKER;
         static {
             final PrivilegedAction<StackWalker> action =
-                    () -> StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
+                () -> StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
             WALKER = AccessController.doPrivileged(action);
         }
 
@@ -736,7 +798,7 @@
 
         private boolean isLoggerImplFrame(String cname) {
             return (cname.equals("java.util.logging.Logger") ||
-                    cname.startsWith("sun.util.logging.PlatformLogger"));
+                cname.startsWith("sun.util.logging.PlatformLogger"));
         }
     }
 }
--- a/src/java.logging/share/classes/java/util/logging/XMLFormatter.java	Fri Jul 03 09:26:16 2020 +0530
+++ b/src/java.logging/share/classes/java/util/logging/XMLFormatter.java	Fri Jul 03 18:58:03 2020 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2020, 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
@@ -219,7 +219,7 @@
         }
 
         sb.append("  <thread>");
-        sb.append(record.getThreadID());
+        sb.append(record.getLongThreadID());
         sb.append("</thread>\n");
 
         if (record.getMessage() != null) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/util/logging/LogRecordThreadIdTest.java	Fri Jul 03 18:58:03 2020 +0530
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+
+
+/*
+ * @test
+ * @bug 8245302
+ * @summary test the relationship between
+ * thread id long and int methods
+ * @build LogRecordThreadIdTest
+ * @run testng/othervm  LogRecordThreadIdTest
+ */
+
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotEquals;
+
+
+
+public class LogRecordThreadIdTest {
+
+    LogRecord record, record1, record2;
+
+    @BeforeTest
+    public void setUp() throws Exception {
+        record  = new LogRecord(Level.INFO, "record");
+        record1 = new LogRecord(Level.INFO, "record1");
+        record2 = new LogRecord(Level.INFO, "record2");
+    }
+
+    /**
+     * Tests threadID setter methods for consistency
+     * with longThreadID
+     */
+    @Test
+    public void testSetThreadId() {
+        record.setThreadID(Integer.MAX_VALUE - 20);
+        record1.setThreadID(Integer.MAX_VALUE - 1);
+        assertEquals(record.getLongThreadID(), Integer.MAX_VALUE - 20L);
+        assertEquals(record.getThreadID(), Integer.MAX_VALUE - 20);
+        assertEquals(record1.getThreadID(), Integer.MAX_VALUE - 1);
+        assertEquals(record1.getLongThreadID(), Integer.MAX_VALUE - 1);
+    }
+
+    /**
+     * Tests longThreadID methods for consistency
+     * with threadID
+     */
+    @Test
+    public void testSetLongThreadId() {
+      record.setLongThreadID(Integer.MAX_VALUE - 20L);
+      record1.setLongThreadID(Integer.MAX_VALUE + 10L);
+      record2.setLongThreadID(Integer.MAX_VALUE);
+      assertEquals(record.getThreadID(), Integer.MAX_VALUE - 20);
+      assertEquals(record.getLongThreadID(), Integer.MAX_VALUE - 20L);
+      assertNotEquals(record1.getThreadID(), Integer.MAX_VALUE + 10L);
+      assertEquals(record1.getLongThreadID(), Integer.MAX_VALUE + 10L);
+      assertEquals(record2.getThreadID(), Integer.MAX_VALUE);
+      assertEquals(record2.getLongThreadID(), Integer.MAX_VALUE);
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/util/logging/SerializeLogRecordTest.java	Fri Jul 03 18:58:03 2020 +0530
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Base64;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.XMLFormatter;
+import java.util.stream.Stream;
+
+/**
+ * @test
+ * @bug 8245302
+ * @summary tests the deprecation of threadID and a new field longThreadID,
+ * test should be run on jdk16 and subsequent versions
+ * @run main/othervm SerializeLogRecordTest
+ */
+public class SerializeLogRecordTest {
+
+    /**
+     * Serializes a log record, encode the serialized bytes in base 64, and
+     * prints pseudo java code that can be cut and pasted into this test.
+     * @param record the log record to serialize, encode in base 64, and for
+     *               which test data will be generated.
+     * @return A string containing the generated pseudo java code.
+     * @throws IOException Unexpected.
+     * @throws ClassNotFoundException  Unexpected.
+     */
+    public static String generate(LogRecord record) throws IOException, ClassNotFoundException {
+
+        XMLFormatter formatter = new XMLFormatter();
+        String str = formatter.format(record);
+
+        // Serialize the given LogRecord
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        final ObjectOutputStream oos = new ObjectOutputStream(baos);
+        oos.writeObject(record);
+        oos.flush();
+        oos.close();
+
+        // Now we're going to perform a number of smoke tests before
+        // generating the Java pseudo code.
+        //
+        // First checks that the log record can be deserialized
+        final ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+        final ObjectInputStream ois = new ObjectInputStream(bais);
+        final LogRecord record2 = (LogRecord)ois.readObject();
+
+        String str2 = formatter.format(record2);
+
+        if (!str.equals(str2)) throw new RuntimeException("Unexpected values in deserialized object:"
+            + "\n\tExpected:  " + str
+            + "\n\tRetrieved: "+str);
+
+        // Now get a Base64 string representation of the serialized bytes.
+        final String base64 = Base64.getEncoder().encodeToString(baos.toByteArray());
+
+        // Check that we can deserialize a log record from the Base64 string
+        // representation we just computed.
+        final ByteArrayInputStream bais2 = new ByteArrayInputStream(Base64.getDecoder().decode(base64));
+        final ObjectInputStream ois2 = new ObjectInputStream(bais2);
+        final LogRecord record3 = (LogRecord)ois2.readObject();
+
+        // Format the new deserialized LogRecord using the SimpleFormatter, and
+        // check that the string representation obtained matches the string
+        // representation of the original LogRecord
+        String str3 = formatter.format(record3);
+        if (!str.equals(str3)) throw new RuntimeException("Unexpected values in deserialized object:"
+            + "\n\tExpected:  " + str
+            + "\n\tRetrieved: "+str);
+
+        // Generates the Java Pseudo code that can be cut & pasted into
+        // this test (see Jdk8SerializedLog and Jdk9SerializedLog below)
+        final StringBuilder sb = new StringBuilder();
+        sb.append("    /**").append('\n');
+        sb.append("     * Base64 encoded string for LogRecord object.").append('\n');
+        sb.append("     * Java version: ").append(System.getProperty("java.version")).append('\n');
+        sb.append("     * threadID: ").append(record.getThreadID()).append('\n');
+        sb.append("     * longThreadID: ").append(record.getLongThreadID()).append('\n');
+        sb.append("     **/").append('\n');
+        sb.append("    final String base64 = ").append("\n          ");
+        final int last = base64.length() - 1;
+        for (int i=0; i<base64.length();i++) {
+            if (i%64 == 0) sb.append("\"");
+            sb.append(base64.charAt(i));
+            if (i%64 == 63 || i == last) {
+                sb.append("\"");
+                if (i == last) sb.append(";\n");
+                else sb.append("\n        + ");
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * An abstract class to test that a log record previously serialized on a
+     * different java version can be deserialized in the current java version.
+     * (see Jdk11SerializedLog and Jdk16SerializedLog below)
+     */
+    public abstract static class SerializedLog {
+        public abstract String getBase64();
+
+        /**
+         * Deserializes the Base64 encoded string returned by {@link
+         * #getBase64()}, and checks that the string representation obtained
+         * matches the original string representation returned by
+         */
+        protected void dotest() {
+            try {
+                final String base64 = getBase64();
+                final ByteArrayInputStream bais =
+                        new ByteArrayInputStream(Base64.getDecoder().decode(base64));
+                final ObjectInputStream ois = new ObjectInputStream(bais);
+                final LogRecord record = (LogRecord)ois.readObject();
+                check(record);
+                System.out.println("PASSED: "+this.getClass().getName()+"\n");
+            } catch (IOException | ClassNotFoundException x) {
+                throw new RuntimeException(x);
+            }
+        }
+        /**
+         * Check that the values of threadID and longThreadID
+         * are correct and consistent when de-serialized from
+         * earlier jdk versions(jdk11)
+         */
+        protected void check(LogRecord r1) {
+            XMLFormatter formatter = new XMLFormatter();
+            int check = Integer.MAX_VALUE - 10;
+            String str = formatter.format(r1);
+            String loggerName = r1.getLoggerName();
+
+            if (loggerName.equals("test2")) {
+                int id = -2147483639;
+                if (r1.getLongThreadID() != Integer.MAX_VALUE + 10L || r1.getThreadID() != id) {
+                    throw new RuntimeException(this.getClass().getName());
+                }
+                else {
+                    System.out.println("Test Integer Check Passed");
+                }
+
+            }
+
+            if (loggerName.equals("test1") || loggerName.equals("test")) {
+                if (loggerName.equals("test1")) {
+                    check = Integer.MAX_VALUE / 2 - 20;
+                }
+
+                int tid = r1.getThreadID();
+                long longThreadID = r1.getLongThreadID();
+                if (tid != check || longThreadID != check || !str.contains("<thread>" + String.valueOf(longThreadID))) {
+                    throw new RuntimeException(this.getClass().getName());
+                }
+                else {
+                    System.out.println("Test Integer Check Passed");
+                }
+            }
+        }
+    }
+
+    public static void generate() {
+        try {
+            LogRecord record = new LogRecord(Level.INFO, "Java Version: {0}");
+            record.setLoggerName("test");
+            record.setThreadID(Integer.MAX_VALUE - 10);
+            record.setParameters(new Object[] {System.getProperty("java.version")});
+            System.out.println(generate(record));
+            LogRecord record1 = new LogRecord(Level.INFO, "Java Version: {0}");
+            record1.setLoggerName("test1");
+            record1.setLongThreadID(Integer.MAX_VALUE/2 - 20);
+            record1.setParameters(new Object[] {System.getProperty("java.version")});
+            System.out.println(generate(record1));
+            LogRecord record2 = new LogRecord(Level.INFO, "Java Version: {0}");
+            record2.setLoggerName("test2");
+            record2.setLongThreadID(Integer.MAX_VALUE + 10L);
+            record2.setParameters(new Object[] {System.getProperty("java.version")});
+            System.out.println(generate(record2));
+        } catch (IOException | ClassNotFoundException x) {
+            throw new RuntimeException(x);
+        }
+    }
+
+    public static class Jdk11SerializedLog extends SerializedLog {
+
+        /**
+         * Base64 encoded string for LogRecord object.
+         * It is generated using generate method and
+         * can be copy pasted as base64 value, for generating
+         * this value, execute this class with an argument value
+         * generate and the test will print out the base64 value
+         * that can be copy pasted below
+         * Java version: 11.0.6
+         **/
+        final String base64 =
+            "rO0ABXNyABtqYXZhLnV0aWwubG9nZ2luZy5Mb2dSZWNvcmRKjVk982lRlgMAC0oA"
+                + "Bm1pbGxpc0kADm5hbm9BZGp1c3RtZW50SgAOc2VxdWVuY2VOdW1iZXJJAAh0aHJl"
+                + "YWRJREwABWxldmVsdAAZTGphdmEvdXRpbC9sb2dnaW5nL0xldmVsO0wACmxvZ2dl"
+                + "ck5hbWV0ABJMamF2YS9sYW5nL1N0cmluZztMAAdtZXNzYWdlcQB+AAJMABJyZXNv"
+                + "dXJjZUJ1bmRsZU5hbWVxAH4AAkwAD3NvdXJjZUNsYXNzTmFtZXEAfgACTAAQc291"
+                + "cmNlTWV0aG9kTmFtZXEAfgACTAAGdGhyb3dudAAVTGphdmEvbGFuZy9UaHJvd2Fi"
+                + "bGU7eHAAAAFycRovVgAFN/AAAAAAAAAAAH////VzcgAXamF2YS51dGlsLmxvZ2dp"
+                + "bmcuTGV2ZWyOiHETUXM2kgIAA0kABXZhbHVlTAAEbmFtZXEAfgACTAAScmVzb3Vy"
+                + "Y2VCdW5kbGVOYW1lcQB+AAJ4cAAAAyB0AARJTkZPdAAic3VuLnV0aWwubG9nZ2lu"
+                + "Zy5yZXNvdXJjZXMubG9nZ2luZ3QABHRlc3R0ABFKYXZhIFZlcnNpb246IHswfXBw"
+                + "cHB3BgEAAAAAAXQABjExLjAuNng=";
+
+
+        @Override
+        public String getBase64() {
+            return base64;
+        }
+
+        @Override
+        protected void check(LogRecord r1) {
+            super.check(r1);
+        }
+
+        public static void test() {
+            new Jdk11SerializedLog().dotest();
+        }
+    }
+
+    public static class Jdk16SerializedLog extends SerializedLog {
+
+        /**
+         * Base64 encoded string for LogRecord object.
+         * It is generated using generate method and
+         * can be copy pasted as base64 value, for generating
+         * this value, execute this class with an argument value
+         * generate and the test will print out the base64 value
+         * that can be copy pasted below
+         * Java version: 16-internal
+         **/
+        final String base64 =
+            "rO0ABXNyABtqYXZhLnV0aWwubG9nZ2luZy5Mb2dSZWNvcmRKjVk982lRlgMADEoA"
+                + "DGxvbmdUaHJlYWRJREoABm1pbGxpc0kADm5hbm9BZGp1c3RtZW50SgAOc2VxdWVu"
+                + "Y2VOdW1iZXJJAAh0aHJlYWRJREwABWxldmVsdAAZTGphdmEvdXRpbC9sb2dnaW5n"
+                + "L0xldmVsO0wACmxvZ2dlck5hbWV0ABJMamF2YS9sYW5nL1N0cmluZztMAAdtZXNz"
+                + "YWdlcQB+AAJMABJyZXNvdXJjZUJ1bmRsZU5hbWVxAH4AAkwAD3NvdXJjZUNsYXNz"
+                + "TmFtZXEAfgACTAAQc291cmNlTWV0aG9kTmFtZXEAfgACTAAGdGhyb3dudAAVTGph"
+                + "dmEvbGFuZy9UaHJvd2FibGU7eHAAAAAAgAAACQAAAXLMALDdAAS+2AAAAAAAAAAC"
+                + "gAAACXNyABdqYXZhLnV0aWwubG9nZ2luZy5MZXZlbI6IcRNRczaSAgADSQAFdmFs"
+                + "dWVMAARuYW1lcQB+AAJMABJyZXNvdXJjZUJ1bmRsZU5hbWVxAH4AAnhwAAADIHQA"
+                + "BElORk90ACJzdW4udXRpbC5sb2dnaW5nLnJlc291cmNlcy5sb2dnaW5ndAAFdGVz"
+                + "dDJ0ABFKYXZhIFZlcnNpb246IHswfXBwcHB3BgEAAAAAAXQACzE2LWludGVybmFs"
+                + "eA==";
+
+
+        @Override
+        public String getBase64() {
+            return base64;
+        }
+
+        @Override
+        protected void check(LogRecord r1) {
+            super.check(r1);
+        }
+
+        public static void test() {
+            new Jdk16SerializedLog().dotest();
+        }
+    }
+
+    static enum TestCase { GENERATE, TESTJDK11, TESTJDK16 };
+
+    public static void main(String[] args) {
+
+
+        // If no args, then run everything....
+        if (args == null || args.length == 0) {
+            args = new String[] { "GENERATE", "TESTJDK11", "TESTJDK16" };
+        }
+
+        // Run the specified test case(s)
+        Stream.of(args).map(x -> TestCase.valueOf(x)).forEach((x) -> {
+            switch(x) {
+                  case GENERATE:  generate(); break;
+                  case TESTJDK11: Jdk11SerializedLog.test(); break;
+                  case TESTJDK16: Jdk16SerializedLog.test(); break;
+            }
+        });
+    }
+}