RFR: 8319873: Add windows implementation for jcmd System.map and System.dump_map
Thomas Stuefe
stuefe at openjdk.org
Tue Aug 20 07:45:54 UTC 2024
On Thu, 15 Aug 2024 13:45:16 GMT, Simon Tooke <stooke at openjdk.org> wrote:
> This is a port of [JDK-8318636](https://github.com/openjdk/jdk/pull/16301) to Windows.
>
> System.map and System.dump_map are implemented using the Windows API and provide roughly the same information in the same format. Most of the heavy lifting was implemented by @tstuefe in #16301 - this PR adds the Windows implementation and enables the common code for Windows 64 bit.
>
> [Sample output (with NMT enabled)](https://github.com/user-attachments/files/16663332/vm_memory_map_760.txt)
Hi Simon,
this is nice, thank you!
Mostly nits.
src/hotspot/os/windows/memMapPrinter_windows.cpp line 3:
> 1: /*
> 2: * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
> 3: * Copyright (c) 2023, 2024, Red Hat, Inc. and/or its affiliates.
New files are added with the current copyright year, unless they are the result of moving.
src/hotspot/os/windows/memMapPrinter_windows.cpp line 32:
> 30:
> 31: #include <limits>
> 32: #include <iostream>
Please use C-headers. We only use C++ headers sparingly. Why do you include these headers?
src/hotspot/os/windows/memMapPrinter_windows.cpp line 63:
> 61: }
> 62:
> 63: const char* getProtectString(char* buffer, size_t bufsiz, DWORD prot) {
Style: In hotspot we use camel case for classes, lower_case_underscore for method, functions etc.
src/hotspot/os/windows/memMapPrinter_windows.cpp line 69:
> 67: const int IP = 3;
> 68: int idx = 4;
> 69: strncpy_s(buffer, bufsiz, "---- ", 7);
We tend to use os::snprintf or jio_snprintf for this. I find strncpy_s a bit fragile since one needs to update both string literal and char count when changing things.
src/hotspot/os/windows/memMapPrinter_windows.cpp line 98:
> 96: buffer[idx++] = 'n';
> 97: } else if (prot != 0) {
> 98: snprintf(buffer, bufsiz, "(0x%x)", prot);
This could truncate for the longest possible value (16+4 chars).
src/hotspot/os/windows/memMapPrinter_windows.cpp line 111:
> 109: buffer[idx++] = 'W';
> 110: }
> 111: buffer[idx] = 0;
Please give us an assert here for idx < bufsiz
src/hotspot/os/windows/memMapPrinter_windows.cpp line 114:
> 112: return buffer;
> 113: }
> 114: const char* getStateString(char* buffer, size_t bufsiz, MEMORY_BASIC_INFORMATION& mInfo) {
We have a utility class for printing to a limited buffer (stringStream). It takes care of buffer limits and zero termination for you. I would use that one where possible.
stringStream ss(buffer, bufsiz);
if (mInfo.State == MEM_COMMIT) {
ss.put('c');
}
...
else { ss.print("0x%x", mInfo.State); }
return buffer;
src/hotspot/os/windows/memMapPrinter_windows.cpp line 145:
> 143: size_t _total_region_size; // combined resident set size
> 144: size_t _total_committed; // combined committed size
> 145: size_t _total_reserved; // combined shared size
I would like us to be careful with terminology since that can get confusing quickly when jumping between OS code and generic code.
In hotspot terminology, "reserved" are parts of the address space that have been allocated for the process, *regardless of commit state*. So, the whole region would count as "reserved", with some pages being also committed, and some not. But on Windows, the MEM_RESERVE state is only given to uncommitted regions, so there is a subtle difference.
I would circumvent the problem by counting only:
- total size (as in sum of region sizes that are not MEM_FREE)
- committed size (as in sum of region sizes that are MEM_COMMIT)
src/hotspot/os/windows/memMapPrinter_windows.cpp line 162:
> 160: outputStream* st = session.out();
> 161: os::print_os_info(st);
> 162: os::print_memory_info(st);
The "danger" here is that both of these functions may bloat in the future and print a lot more than today; and that we may want to use this printout in places where we also print out OS info and memory info, and therefore get duplicated printout (e.g. hs-err printing or jcmd VM.info).
But I would print out the number of mappings you counted, and the total size of committed regions.
src/hotspot/os/windows/memMapPrinter_windows.cpp line 243:
> 241: printer.print_header();
> 242:
> 243: MEMORY_BASIC_INFORMATION mInfo;
Just to be sure, I would zero out mInfo.
src/hotspot/os/windows/memMapPrinter_windows.cpp line 246:
> 244: MappingInfo info;
> 245:
> 246: for (char* ptr = 0; VirtualQueryEx(hProcess, ptr, &mInfo, sizeof(mInfo)) == sizeof(mInfo); ptr += mInfo.RegionSize) {
I would add a failsafe breakout in case we made a thinking error somewhere or the address space is insanely fragmented. Maybe break out after a million regions? Or, after a certain time (e.g. 10 seconds). I also would assert for RegionSize > 0
src/hotspot/share/services/diagnosticCommand.cpp line 1207:
> 1205: const char* absname = os::Posix::realpath(name, tmp, sizeof(tmp));
> 1206: name = absname != nullptr ? absname : name;
> 1207: #endif
I wince a bit a the new ifdefs. Possibly for a separate RFE, it would be nice to have a function os::realpath() that uses realpath(2) on POSIX platforms, _fullpath on Windows.
-------------
PR Review: https://git.openjdk.org/jdk/pull/20597#pullrequestreview-2247042750
PR Review Comment: https://git.openjdk.org/jdk/pull/20597#discussion_r1722735615
PR Review Comment: https://git.openjdk.org/jdk/pull/20597#discussion_r1722743452
PR Review Comment: https://git.openjdk.org/jdk/pull/20597#discussion_r1722745964
PR Review Comment: https://git.openjdk.org/jdk/pull/20597#discussion_r1722766129
PR Review Comment: https://git.openjdk.org/jdk/pull/20597#discussion_r1722763766
PR Review Comment: https://git.openjdk.org/jdk/pull/20597#discussion_r1722757477
PR Review Comment: https://git.openjdk.org/jdk/pull/20597#discussion_r1722770690
PR Review Comment: https://git.openjdk.org/jdk/pull/20597#discussion_r1722783949
PR Review Comment: https://git.openjdk.org/jdk/pull/20597#discussion_r1722795939
PR Review Comment: https://git.openjdk.org/jdk/pull/20597#discussion_r1722809524
PR Review Comment: https://git.openjdk.org/jdk/pull/20597#discussion_r1722807479
PR Review Comment: https://git.openjdk.org/jdk/pull/20597#discussion_r1722801573
More information about the serviceability-dev
mailing list