JDK-8238649 : Call new Win32 API SetThreadDescription in os::set_native_thread_name
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 15
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_10
  • CPU: x86
  • Submitted: 2020-02-07
  • Updated: 2021-11-16
  • Resolved: 2021-06-15
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 17 JDK 18
17.0.2Fixed 18 b02Fixed
Related Reports
Relates :  
Relates :  
Description
On 7/02/2020 4:07 am, Gaisbauer, Markus wrote:
> Hi,
> 
> I am looking for a sponsor who could create a ticket for the following proposal:
> 
> Microsoft recently introduced a new API to assign a name to native Windows threads.
> https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription
> 
> These thread names can be shown by debuggers, C++ profilers, etc. The new API is available since either Windows 10 1607 or Windows Server 2016.
> 
> The JVM already tries to set a native thread name both for all internal JVM threads and all Java threads (except main).
> 
> But the Windows implementation of os::set_native_thread_name currently uses a weird hack described here.
> https://docs.microsoft.com/en-us/visualstudio/debugger/how-to-set-a-thread-name-in-native-code?view=vs-2015&redirectedfrom=MSDN
> 
> For this hack, debugger has to be already attached when a thread starts.
> 
> I propose to check in os::set_native_thread_name if SetThreadDescription is available. If yes, either call it instead or in addition to the current code.
> 
> Here is some prototype code that worked for me:
> 
> typedef HRESULT(WINAPI *SetThreadDescriptionT)(HANDLE, PCWSTR);
> 
> static SetThreadDescriptionT getSetThreadDescriptionT() {
>    HMODULE kernel32 = GetModuleHandle("Kernel32.dll");
>    return kernel32 ? reinterpret_cast<SetThreadDescriptionT>(GetProcAddress(kernel32, "SetThreadDescription")) : nullptr;
> }
> 
> static LPWSTR utf8_decode(const char *name) {
>    if (name == nullptr) return nullptr;
>    int name_len = (int) strlen(name);
>    int size_needed = MultiByteToWideChar(CP_UTF8, 0, name, name_len, NULL, 0);
>    size_t buffer_len = sizeof(wchar_t) * (size_needed + 1);
>    LPWSTR result = (LPWSTR) os::malloc(buffer_len, mtInternal);
>    memset(result, 0, buffer_len);
>    MultiByteToWideChar(CP_UTF8, 0, name, name_len, result, size_needed);
>    return result;
> }
> 
> void os::set_native_thread_name(const char *name) {
> 
>    // First try calling SetThreadDescription available since Windows 10 1607 / Windows Server 2016
>    // See: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription
> 
>    static SetThreadDescriptionT SetThreadDescription = getSetThreadDescriptionT();
>    if (SetThreadDescription) {
>      LPWSTR nameWide = utf8_decode(name);
>      if (nameWide != nullptr) {
>        SetThreadDescription(GetCurrentThread(), nameWide);
>        os::free(nameWide);
>      }
>      return;
>    }
> 
>    // fallback
>    ...
> }
> 
> Best regards,
> Markus
Comments
Fix request (17u) Clean backport of a Windows-specific enhancement. Note, there is a follow-up fix: JDK-8268927 to this backport.
05-11-2021

Changeset: 9f3c7e74 Author: David Holmes <dholmes@openjdk.org> Date: 2021-06-15 02:12:57 +0000 URL: https://git.openjdk.java.net/jdk/commit/9f3c7e74ff00a7550742ed8b9d6671c2d4bb6041
15-06-2021

Deferring to 18 as I can't get any reviewers for this change before RDP1.
08-06-2021

Using the new API was quite straight forward, but verifying that it had worked correctly was far more challenging. It seems there are no tools that use the new GetThreadDescription API to display thread names, so no easy check that this had worked. While Visual Studio will use it, it also uses the old debugger mechanism, so we wouldn't be able to tell the difference. Writing a Windows-only test was one possibility, but the conversion to/from Unicode and java.lang.String would make that test very cumbersome in itself (for something that should be trivial!). So instead for debug builds I read back the thread name using GetThreadDescription and check that the name we set and the name we read are the same. Here's a faked assertion failure (when the names are actually the same) to show the output: # Internal Error (t:\workspace\open\src\hotspot\os\windows\os_windows.cpp:935), pid=22876, tid=27676 # assert(res == 2 && !UseNewCode) failed: Name strings were not the same! Set: G1 Main Marker, but read: G1 Main Marker
02-06-2021