<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <p>If you just want to be able to copy memory from A to B, you can
      use the code you have shown, yes.</p>
    <p>I'm not 100% sure of the use of the everything segment here.
      Perhaps you want to do that to avoid doing
      MemorySegment::ofBuffer. While I understand that, as mentioned, we
      have improved that factory, so I'm not sure the creation of the
      additional segment view should be problematic (e.g. it should be
      escape analyzed where it matters).<br>
    </p>
    <p>You can also create a downcall method handle for memcpy, and then
      pass to it the two pointers you want to copy. The pointers can
      either be passed as memory segments, or as plain longs, depending
      on how you describe the memcpy arguments to the Linker (of course
      the latter is more unsafe and not really recommended, but an
      option nevertheless).</p>
    <p>Maurizio<br>
    </p>
    <p><br>
    </p>
    <div class="moz-cite-prefix">On 06/01/2025 13:34, Sergio Selos
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CANFht85B8oKk5ie56_6gUd2JzY_zs=KZqgLNAerw7xY1efomeg@mail.gmail.com">
      
      <div dir="ltr">
        <div dir="ltr">Hi Everyone,
          <div><br>
          </div>
          <div>Thanks for taking the time to analyze and reply to my
            question. I think the classic C memcpy would solve my
            problem, and I could do it through some JNI code, but I
            would be happy to be able to use Panama (pure Java) instead.
            I posted this question on SO and someone has suggested the
            solution below using Panama. I haven't tried it yet.<br>
            <br>
            <a href="https://stackoverflow.com/a/79311822/28712954" moz-do-not-send="true" class="moz-txt-link-freetext">https://stackoverflow.com/a/79311822/28712954</a></div>
          <div><br>
          </div>
          <div>
            <pre class="gmail-lang-java gmail-s-code-block" style="margin-top:0px;border:0px;font-variant-numeric:inherit;font-variant-east-asian:inherit;font-variant-alternates:inherit;font-stretch:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;vertical-align:baseline;box-sizing:inherit;width:auto;max-height:600px;overflow:auto;color:rgb(12,13,14)"><code class="gmail-hljs gmail-language-java" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;vertical-align:baseline;box-sizing:inherit;background-color:transparent;white-space:inherit"><span class="gmail-hljs-comment" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">// With FFM API:</span>
<span class="gmail-hljs-keyword" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">static</span> <span class="gmail-hljs-keyword" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">final</span> <span class="gmail-hljs-type" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">MemorySegment</span> <span class="gmail-hljs-variable" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">EVERYTHING_SEGMENT</span> <span class="gmail-hljs-operator" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">=</span> MemorySegment.NULL.reinterpret(Long.MAX_VALUE);

<span class="gmail-hljs-meta" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">@Override</span>
<span class="gmail-hljs-keyword" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">public</span> <span class="gmail-hljs-keyword" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">void</span> <span class="gmail-hljs-title gmail-function_" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">getByteBuffer</span><span class="gmail-hljs-params" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">(<span class="gmail-hljs-type" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;vertical-align:baseline;box-sizing:inherit">long</span> address, ByteBuffer dst, <span class="gmail-hljs-type" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;vertical-align:baseline;box-sizing:inherit">int</span> len)</span> {
    <span class="gmail-hljs-keyword" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">if</span> (!dst.isDirect()) {
        <span class="gmail-hljs-keyword" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">throw</span> <span class="gmail-hljs-keyword" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">new</span> <span class="gmail-hljs-title gmail-class_" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">RuntimeException</span>(<span class="gmail-hljs-string" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">"getByteBuffer can only take a direct byte buffer!"</span>);
    }

    <span class="gmail-hljs-type" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">long</span> <span class="gmail-hljs-variable" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">dstAddress</span> <span class="gmail-hljs-operator" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">=</span> (<span class="gmail-hljs-type" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">long</span>) addressField.get(dst) + dst.position();
    EVERYTHING_SEGMENT.copyFrom(<span class="gmail-hljs-built_in" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant:inherit;font-weight:inherit;font-stretch:inherit;line-height:inherit;font-family:inherit;font-size-adjust:inherit;font-kerning:inherit;font-feature-settings:inherit;font-size:13px;vertical-align:baseline;box-sizing:inherit">this</span>.segment, offset, dstAddress, len);
    dst.position(dst.position() + len);
}</code></pre>
          </div>
        </div>
        All the best,
        <div><br>
        </div>
        <div>-Sergio</div>
        <div><br>
        </div>
        <div><br>
          <div class="gmail_quote gmail_quote_container">
            <div dir="ltr" class="gmail_attr">On Mon, Jan 6, 2025 at
              6:57 AM <<a href="mailto:rsmogura@icloud.com" moz-do-not-send="true" class="moz-txt-link-freetext">rsmogura@icloud.com</a>>
              wrote:<br>
            </div>
            <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi,<br>
              <br>
              I wonder if this concern can be because of using Arena
              arena = Arena.ofConfined(), or due to @Overriding method
              and inability to inline method.<br>
              <br>
              What do you think (sorry if I missed parts of this
              discussion).<br>
              <br>
              Best regards,<br>
              Rado<br>
              <br>
              > Wiadomość napisana przez Jorn Vernee <<a href="mailto:jorn.vernee@oracle.com" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">jorn.vernee@oracle.com</a>>
              w dniu 6 sty 2025, o godz. 12:25:<br>
              > <br>
              > Hello,<br>
              > <br>
              > Have you verified that garbage is actually being
              generated when using FFM?<br>
              > <br>
              > If I set up a test program based on your snippet [1],
              and run it with -XX:CompileCommand=TraceEscapeAnalysis,...
              I don't actually see any escaping allocations.<br>
              > <br>
              > Jorn<br>
              > <br>
              > [1]:<br>
              > <br>
              > import java.lang.foreign.Arena;<br>
              > import java.lang.foreign.MemorySegment;<br>
              > import java.nio.ByteBuffer;<br>
              > <br>
              > public class TestOfBuffer {<br>
              > <br>
              >     long address = 0;<br>
              >     MemorySegment segment;<br>
              > <br>
              >     public static void main(String[] args) {<br>
              >         TestOfBuffer recv = new TestOfBuffer();<br>
              >         recv.segment = Arena.global().allocate(100);<br>
              > <br>
              >         ByteBuffer bb =
              ByteBuffer.allocateDirect(10);<br>
              >         for (int i = 0; i < 20_000; i++) {<br>
              >             recv.payload(0, bb, 10);<br>
              >             bb.flip();<br>
              >         }<br>
              >     }<br>
              > <br>
              >     public void payload(long address, ByteBuffer dst,
              int len) {<br>
              >         if (!dst.isDirect()) {<br>
              >             throw new RuntimeException("getByteBuffer
              can only take a direct byte buffer!");<br>
              >         }<br>
              > <br>
              >         long offset = address - this.address; //
              offset in our 'segment'<br>
              > <br>
              >         // Wrap the destination ByteBuffer in a
              temporary segment<br>
              >         // This segment's data starts at
              dst.position()<br>
              >         MemorySegment dstSegment =
              MemorySegment.ofBuffer(dst); // <====== temp memory
              segment object<br>
              > <br>
              >         // Copy from 'segment' at 'offset' →
              dstSegment at offset 0 → length = 'len'<br>
              >         MemorySegment.copy(this.segment, offset,
              dstSegment, 0, len);<br>
              >         dst.position(dst.position() + len);<br>
              >     }<br>
              > }<br>
              > <br>
              > On 27-12-2024 02:05, Sergio Selos wrote:<br>
              >> Hello,<br>
              >> <br>
              >> We have a project using sun.misc.Unsafe that we
              are migrating to the new FFM API. The project is at <a href="https://www.github.com/coralblocks/CoralRing" rel="noreferrer" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">https://www.github.com/coralblocks/CoralRing</a><br>
              >> <br>
              >> For our particular systems (mostly financial low
              latency systems) it is important not to create any garbage
              (temp discarded instances) when receiving a message.<br>
              >> <br>
              >> We encountered an issue when copying from native
              memory straight into a direct ByteBuffer using the FFM
              API.<br>
              >> <br>
              >> Using sun.misc.Unsafe, copying from memory to a
              ByteBuffer can be done without creating temporary objects
              and garbage collector overhead. However, with the FFM API,
              achieving the same does not seem currently possible
              without generating garbage via a call to
              MemorySegment.ofBuffer.<br>
              >> <br>
              >> Does the FFM dev team plan to address this issue
              and provide a garbage-free way to perform this copy, like
              we currently can with sun.misc.Unsafe?<br>
              >> <br>
              >> Maybe there is already a way and we are just
              unaware how to do it.<br>
              >> <br>
              >> Below the current code we have with
              sun.misc.Unsafe, which does not produce any garbage, and
              the only way we are aware of to do it with the FFM API,
              which produces garbage.<br>
              >> <br>
              >> Thanks and let me know if you need any more
              details about this and/or if I can help with anything.<br>
              >> <br>
              >> All the best,<br>
              >> <br>
              >> -Sergio<br>
              >> <br>
              >> // With sun.misc.Unsafe:<br>
              >> @Override<br>
              >> public void getByteBuffer(long address,
              ByteBuffer dst, int len) {<br>
              >>     if (!dst.isDirect()) {<br>
              >>         throw new RuntimeException("getByteBuffer
              can only take a direct byte buffer!");<br>
              >>     }<br>
              >>     try {<br>
              >>         long dstAddress = (long)
              addressField.get(dst); // get the memory address of this
              ByteBuffer<br>
              >>         dstAddress += dst.position(); // adjust
              the address for the ByteBuffer current position<br>
              >>         unsafe.copyMemory(address, dstAddress,
              len); // copy over<br>
              >>         dst.position(dst.position() + len); //
              adjust the ByteBuffer position to reflect the copy
              operation<br>
              >>     } catch(Exception e) {<br>
              >>         throw new RuntimeException(e);<br>
              >>     }<br>
              >> }<br>
              >> <br>
              >> // With FFM API:<br>
              >> @Override<br>
              >> public void getByteBuffer(long address,
              ByteBuffer dst, int len) {<br>
              >>     if (!dst.isDirect()) {<br>
              >>         throw new RuntimeException("getByteBuffer
              can only take a direct byte buffer!");<br>
              >>     }<br>
              >> <br>
              >>     long offset = address - this.address; //
              offset in our 'segment'<br>
              >> <br>
              >>     try (Arena arena = Arena.ofConfined()) { //
              <==== probably creating a temp object here too<br>
              >>         // Wrap the destination ByteBuffer in a
              temporary segment<br>
              >>         // This segment's data starts at
              dst.position()<br>
              >>         MemorySegment dstSegment =
              MemorySegment.ofBuffer(dst, arena); // <====== temp
              memory segment object<br>
              >> <br>
              >>         // Copy from 'segment' at 'offset' →
              dstSegment at offset 0 → length = 'len'<br>
              >>         dstSegment.copyFrom(this.segment, offset,
              0, len);<br>
              >>     }<br>
              >>     dst.position(dst.position() + len);<br>
              >> }<br>
              >> <br>
              >> <br>
              >> <br>
              >> <br>
              >> <br>
              <br>
            </blockquote>
          </div>
        </div>
      </div>
    </blockquote>
  </body>
</html>