JDK-8357579 : Compilation error: first argument in call to 'memset' is a pointer to non-trivially copyable type
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 25
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2025-05-21
  • Updated: 2025-08-26
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 26
26Unresolved
Related Reports
Causes :  
Duplicate :  
Description
ADDITIONAL SYSTEM INFORMATION :
clang 20 on Linux

A DESCRIPTION OF THE PROBLEM :
With clang 20, resolveFieldEntry.cpp and resolveMethodEntry.cpp break the build with similar warnings:

src/hotspot/share/oops/resolvedFieldEntry.cpp:49:10: error: first argument in call to 'memset' is a pointer to non-trivially copyable type 'ResolvedFieldEntry' [-Werror,-Wnontrivial-memcall]
   49 | memset(this, 0, sizeof(*this));
      | ^
src/hotspot/share/oops/resolvedFieldEntry.cpp:49:10: note: explicitly cast the pointer to silence this warning
   49 | memset(this, 0, sizeof(*this));
      | ^
      | (void*)
src/hotspot/share/oops/resolvedMethodEntry.cpp:43:12: error: first argument in call to 'memset' is a pointer to non-trivially copyable type 'ResolvedMethodEntry' [-Werror,-Wnontrivial-memcall]
   43 | memset(this, 0, sizeof(*this));
      | ^
src/hotspot/share/oops/resolvedMethodEntry.cpp:43:12: note: explicitly cast the pointer to silence this warning
   43 | memset(this, 0, sizeof(*this));
      | ^
      | (void*)
XXXX/src/hotspot/share/oops/resolvedMethodEntry.cpp:48:12: error: first argument in call to 'memset' is a pointer to non-trivially copyable type 'ResolvedMethodEntry' [-Werror,-Wnontrivial-memcall]
   48 | memset(this, 0, sizeof(*this));
      | ^
XXXX/src/hotspot/share/oops/resolvedMethodEntry.cpp:48:12: note: explicitly cast the pointer to silence this warning
   48 | memset(this, 0, sizeof(*this));
      | ^
      | (void*)


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Build with --with-toolchain-type=clang when clang is version 20.
Comments
Sorry, my above comment is incorrect regarding remove_unshareable_info(). The problem is not with ResolvedFieldEntry::remove_unshareable_info(), but rather the ResolvedFieldEntries that are not cleaned by this function. https://github.com/openjdk/jdk/blob/0f7c0e956e278458e3d875bbda174e3b9e143135/src/hotspot/share/oops/cpCache.cpp#L433-L438 if (resolved && AOTConstantPoolResolver::is_resolution_deterministic(src_cp, cp_index)) { rfi->mark_and_relocate(); /// <--- HERE archived = true; } else { rfi->remove_unshareable_info(); } Note that rfi is allocated from within the metaspace, so originally it contains all zeros. However, sometimes we read a ResolvedFieldEntry from a GrowableArray and store it inside *rfi. If we use the default copy constructor, the copy inside the GrowableArray may have junk in its gaps, and the junk will leak into *rfi. If I remember correctly, this problems is most prominent on Windows. It's probably because Windows likes to use aligned copies to move stack variables into the GrowableArray, taking whatever junk from the stack.
26-08-2025

[~iklam] So my supposition was correct. Padding is very not portable, though one can figure it out from ABI docs. I need to go read about object lifetime again before I can perhaps suggest a way out of this.
26-08-2025

[~kbarrett] The problem with the default copy constructor is it might copy random values from the padding bytes: InstanceKlass* _field_holder; // Field holder klass int _field_offset; // Field offset in bytes u2 _field_index; // Index into field information in holder InstanceKlass u2 _cpool_index; // Constant pool index u1 _tos_state; // TOS state u1 _flags; // Flags: [0000|00|is_final|is_volatile] u1 _get_code, _put_code; // Get and Put bytecodes of the field // 1 padding bytes on 32-bit // 5 padding bytes on 64-bit This will cause failures in test/hotspot/jtreg/runtime/cds/DeterministicDump.java on certain platforms. If you want to use the copy constructors, you need to add the padding bytes by hand and explicitly set them to zero in ResolvedFieldEntry::remove_unshareable_info(). I am not sure if structure padding is compiler-specific or not, so it might be difficult to write portable code.
25-08-2025

A pull request was submitted for review. Branch: master URL: https://git.openjdk.org/jdk/pull/26098 Date: 2025-07-02 16:29:27 +0000
02-07-2025

The warning is obviously correct; the class involved is not trivially copyable. The first thing I wondered, is why is the class not trivially copyable. It defines a private helper `copy_from` (which just does member-by-member copying, so what default copyiers are spedified to do) and has the copy ctor and assignment operators call it. So why don't we just use the default copy ctor and assignment operator? That is, why isn't remove_unshareable_info something like ``` *this = ResolvedFieldEntry(_cpool_index); ``` with no `memset` at all? Maybe there is some issue with padding vs reproducible builds? But I can't find any discussion of that, either in code comments or in the review of JDK-8293980 (which added `copy_from`). I found no explanation at all for the introduction of `copy_from`. And without more information, it's hard to suggest alternatives.
23-05-2025