diff a/doc/panama_jextract.html b/doc/panama_jextract.html
--- a/doc/panama_jextract.html
+++ b/doc/panama_jextract.html
@@ -144,11 +144,11 @@
 </ul></li>
 <li><a href="#using-sqlite3-library-from-java-mac-os">Using sqlite3 library from Java (Mac OS)</a>
 <ul>
 <li><a href="#jextract-sqlite3.h">jextract sqlite3.h</a></li>
 <li><a href="#java-program-that-uses-sqlite3">Java program that uses sqlite3</a></li>
-<li><a href="#compiling-and-running-the-libgit2-sample-1">Compiling and running the libgit2 sample</a></li>
+<li><a href="#compiling-and-running-the-sqlite3-sample">Compiling and running the sqlite3 sample</a></li>
 </ul></li>
 </ul></li>
 </ul>
 </nav>
 <?xml version="1.0" encoding="utf-8"?>
@@ -645,11 +645,11 @@
 <span id="cb31-89"><a href="#cb31-89"></a></span>
 <span id="cb31-90"><a href="#cb31-90"></a>            <span class="fu">sqlite3_close</span>(dbPtr);</span>
 <span id="cb31-91"><a href="#cb31-91"></a>        }</span>
 <span id="cb31-92"><a href="#cb31-92"></a>    }</span>
 <span id="cb31-93"><a href="#cb31-93"></a>}</span></code></pre></div>
-<h3 id="compiling-and-running-the-libgit2-sample-1">Compiling and running the libgit2 sample</h3>
+<h3 id="compiling-and-running-the-sqlite3-sample">Compiling and running the sqlite3 sample</h3>
 <div class="sourceCode" id="cb32"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb32-1"><a href="#cb32-1"></a></span>
 <span id="cb32-2"><a href="#cb32-2"></a><span class="ex">java</span> -Dforeign.restricted=permit \</span>
 <span id="cb32-3"><a href="#cb32-3"></a>   --add-modules jdk.incubator.foreign \</span>
 <span id="cb32-4"><a href="#cb32-4"></a>   -Djava.library.path=/usr/lib SqliteMain.java</span></code></pre></div>
 </body>
diff a/doc/panama_jextract.md b/doc/panama_jextract.md
--- a/doc/panama_jextract.md
+++ b/doc/panama_jextract.md
@@ -666,11 +666,11 @@
     }
 }
 
 ```
 
-### Compiling and running the libgit2 sample
+### Compiling and running the sqlite3 sample
 
 ```sh
 
 java -Dforeign.restricted=permit \
    --add-modules jdk.incubator.foreign \
diff a/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/HeaderBuilder.java b/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/HeaderBuilder.java
--- a/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/HeaderBuilder.java
+++ b/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/HeaderBuilder.java
@@ -154,7 +154,16 @@
         sb.append("return RuntimeHelper.upcallStub(" + className + ".class, fi, " + functionGetCallString(className, fDesc) + ", " +
                 "\"" + mtype.toMethodDescriptorString() + "\");\n");
         decrAlign();
         indent();
         sb.append("}\n");
+
+        indent();
+        sb.append(PUB_MODS + "MemoryAddress allocate(" + className + " fi, CScope scope) {\n");
+        incrAlign();
+        indent();
+        sb.append("return scope.register(allocate(fi)).baseAddress();\n");
+        decrAlign();
+        indent();
+        sb.append("}\n");
     }
 }
diff a/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/OutputFactory.java b/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/OutputFactory.java
--- a/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/OutputFactory.java
+++ b/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/OutputFactory.java
@@ -153,10 +153,11 @@
         try {
             List<JavaFileObject> files = new ArrayList<>();
             files.add(builder.build());
             files.addAll(constantHelper.getClasses());
             files.add(fileFromString(pkgName,"RuntimeHelper", getRuntimeHelperSource()));
+            files.add(getCScopeFile(pkgName));
             files.add(getCstringFile(pkgName));
             files.add(getCpointerFile(pkgName));
             files.addAll(getPrimitiveTypeFiles(pkgName));
             return files.toArray(new JavaFileObject[0]);
         } catch (IOException ex) {
@@ -179,10 +180,14 @@
         } catch (Exception ex) {
             ex.printStackTrace();
         }
     }
 
+    private JavaFileObject getCScopeFile(String pkgName) throws IOException, URISyntaxException {
+        return getTemplateFile(pkgName, "CScope", "resources/CScope.java.template");
+    }
+
     private JavaFileObject getCstringFile(String pkgName) throws IOException, URISyntaxException {
         return getTemplateFile(pkgName, "Cstring", "resources/Cstring.java.template");
     }
 
     private JavaFileObject getCpointerFile(String pkgName) throws IOException, URISyntaxException {
diff a/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/resources/C-X.java.template b/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/resources/C-X.java.template
--- a/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/resources/C-X.java.template
+++ b/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/resources/C-X.java.template
@@ -48,22 +48,22 @@
         var seg = MemorySegment.allocateNative(LAYOUT);
         handle.set(seg.baseAddress(), value);
         return seg;
     }
 
-    public static MemoryAddress allocate(${CARRIER} value, NativeAllocationScope scope) {
+    public static MemoryAddress allocate(${CARRIER} value, CScope scope) {
         var addr = scope.allocate(LAYOUT);
         handle.set(addr, value);
         return addr;
     }
 
     public static MemorySegment allocateArray(int length) {
         var arrLayout = MemoryLayout.ofSequence(length, LAYOUT);
         return MemorySegment.allocateNative(arrLayout);
     }
 
-    public static MemoryAddress allocateArray(int length, NativeAllocationScope scope) {
+    public static MemoryAddress allocateArray(int length, CScope scope) {
         var arrLayout = MemoryLayout.ofSequence(length, LAYOUT);
         return scope.allocate(arrLayout);
     }
 
     public static MemorySegment allocateArray(${CARRIER}[] arr) {
@@ -71,11 +71,11 @@
         var seg = MemorySegment.allocateNative(arrLayout);
         seg.copyFrom(MemorySegment.ofArray(arr));
         return seg;
     }
 
-    public static MemoryAddress allocateArray(${CARRIER}[] arr, NativeAllocationScope scope) {
+    public static MemoryAddress allocateArray(${CARRIER}[] arr, CScope scope) {
         var arrLayout = MemoryLayout.ofSequence(arr.length, LAYOUT);
         var addr = scope.allocate(arrLayout);
         addr.segment().copyFrom(MemorySegment.ofArray(arr));
         return addr;
     }
diff a/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/resources/CScope.java.template b/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/resources/CScope.java.template
--- /dev/null
+++ b/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/resources/CScope.java.template
@@ -0,0 +1,51 @@
+// Generated by jextract
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.OptionalLong;
+import jdk.incubator.foreign.MemoryAddress;
+import jdk.incubator.foreign.MemorySegment;
+import jdk.incubator.foreign.NativeAllocationScope;
+
+public final class CScope extends NativeAllocationScope {
+    private final NativeAllocationScope impl;
+    private final List<MemorySegment> segments = new ArrayList<>();
+
+    public CScope() {
+        impl = NativeAllocationScope.unboundedScope();
+    }
+
+    public CScope(long size) {
+        impl = NativeAllocationScope.boundedScope(size);
+    }
+
+    @Override
+    public OptionalLong byteSize() {
+        return impl.byteSize();
+    }
+
+    @Override
+    public long allocatedBytes() {
+        return impl.allocatedBytes();
+    }
+
+    @Override
+    public MemoryAddress allocate(long bytesSize, long bytesAlignment) {
+        return impl.allocate(bytesSize, bytesAlignment);
+    }
+
+    @Override
+    public void close() {
+        for (var seg : segments) {
+            seg.close();
+        }
+        impl.close();
+    }
+
+    public MemorySegment register(MemorySegment seg) {
+        segments.add(Objects.requireNonNull(seg));
+        return seg;
+    }
+}
+
diff a/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/resources/Cpointer.java.template b/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/resources/Cpointer.java.template
--- a/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/resources/Cpointer.java.template
+++ b/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/resources/Cpointer.java.template
@@ -1,9 +1,8 @@
 // Generated by jextract
 
 import java.lang.invoke.VarHandle;
-import jdk.incubator.foreign.NativeAllocationScope;
 import jdk.incubator.foreign.MemoryAddress;
 import jdk.incubator.foreign.MemoryHandles;
 import jdk.incubator.foreign.MemoryLayout;
 import jdk.incubator.foreign.MemorySegment;
 import static jdk.incubator.foreign.CSupport.C_POINTER;
@@ -44,22 +43,22 @@
         var seg = MemorySegment.allocateNative(LAYOUT);
         handle.set(seg.baseAddress(), value);
         return seg;
     }
 
-    public static MemoryAddress allocate(MemoryAddress value, NativeAllocationScope scope) {
+    public static MemoryAddress allocate(MemoryAddress value, CScope scope) {
         var addr = scope.allocate(LAYOUT);
         handle.set(addr, value);
         return addr;
     }
 
     public static MemorySegment allocateArray(int length) {
         var arrLayout = MemoryLayout.ofSequence(length, LAYOUT);
         return MemorySegment.allocateNative(arrLayout);
     }
 
-    public static MemoryAddress allocateArray(int length, NativeAllocationScope scope) {
+    public static MemoryAddress allocateArray(int length, CScope scope) {
         var arrLayout = MemoryLayout.ofSequence(length, LAYOUT);
         return scope.allocate(arrLayout);
     }
 
     public static long sizeof() {
diff a/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/resources/Cstring.java.template b/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/resources/Cstring.java.template
--- a/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/resources/Cstring.java.template
+++ b/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/resources/Cstring.java.template
@@ -1,10 +1,9 @@
 // Generated by jextract
 
 import java.lang.invoke.VarHandle;
 import java.nio.charset.Charset;
-import jdk.incubator.foreign.NativeAllocationScope;
 import jdk.incubator.foreign.MemoryAddress;
 import jdk.incubator.foreign.MemoryLayout;
 import jdk.incubator.foreign.MemorySegment;
 import static jdk.incubator.foreign.CSupport.C_CHAR;
 
@@ -25,11 +24,11 @@
         MemoryAddress addr = segment.baseAddress();
         copy(addr, bytes);
         return segment;
     }
 
-    private static MemoryAddress toCString(byte[] bytes, NativeAllocationScope scope) {
+    private static MemoryAddress toCString(byte[] bytes, CScope scope) {
         MemoryLayout strLayout = MemoryLayout.ofSequence(bytes.length + 1, C_CHAR);
         MemoryAddress addr = scope.allocate(strLayout);
         addr.segment().copyFrom(MemorySegment.ofArray(bytes));
         return addr;
     }
@@ -57,15 +56,15 @@
 
     public static MemorySegment toCString(String str, Charset charset) {
          return toCString(str.getBytes(charset));
     }
 
-    public static MemoryAddress toCString(String str, NativeAllocationScope scope) {
+    public static MemoryAddress toCString(String str, CScope scope) {
         return toCString(str.getBytes(), scope);
     }
 
-    public static MemoryAddress toCString(String str, Charset charset, NativeAllocationScope scope) {
+    public static MemoryAddress toCString(String str, Charset charset, CScope scope) {
         return toCString(str.getBytes(charset), scope);
     }
 
     public static String toJavaString(MemoryAddress addr) {
         StringBuilder buf = new StringBuilder();
diff a/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/resources/RuntimeHelper.java.template b/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/resources/RuntimeHelper.java.template
--- a/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/resources/RuntimeHelper.java.template
+++ b/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/resources/RuntimeHelper.java.template
@@ -11,16 +11,12 @@
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
 import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;
-import java.util.Objects;
 import java.util.Optional;
-import java.util.OptionalLong;
 
 import static ${C_LANG}.*;
 
 public class RuntimeHelper {
 
@@ -84,51 +80,10 @@
         } catch (Throwable ex) {
             throw new AssertionError(ex);
         }
     }
 
-    public static final class CScope extends NativeAllocationScope {
-        private final NativeAllocationScope impl;
-        private final List<MemorySegment> segments = new ArrayList<>();
-
-        public CScope() {
-            impl = NativeAllocationScope.unboundedScope();
-        }
-
-        public CScope(long size) {
-            impl = NativeAllocationScope.boundedScope(size);
-        }
-
-        @Override
-        public OptionalLong byteSize() {
-            return impl.byteSize();
-        }
-
-        @Override
-        public long allocatedBytes() {
-            return impl.allocatedBytes();
-        }
-
-        @Override
-        public MemoryAddress allocate(long bytesSize, long bytesAlignment) {
-            return impl.allocate(bytesSize, bytesAlignment);
-        }
-
-        @Override
-        public void close() {
-            for (var seg : segments) {
-                seg.close();
-            }
-            impl.close();
-        }
-
-        public MemorySegment register(MemorySegment seg) {
-            segments.add(Objects.requireNonNull(seg));
-            return seg;
-        }
-    }
-
     private static class VarargsInvoker {
         private static final MethodHandle INVOKE_MH;
         private final MemoryAddress symbol;
         private final MethodType varargs;
         private final FunctionDescriptor function;
diff a/test/jdk/tools/jextract/test8241925/LibTest8241925Test.java b/test/jdk/tools/jextract/test8241925/LibTest8241925Test.java
--- a/test/jdk/tools/jextract/test8241925/LibTest8241925Test.java
+++ b/test/jdk/tools/jextract/test8241925/LibTest8241925Test.java
@@ -21,11 +21,10 @@
  * questions.
  */
 
 import java.util.stream.DoubleStream;
 import java.util.stream.IntStream;
-import jdk.incubator.foreign.NativeAllocationScope;
 import org.testng.annotations.Test;
 import test.jextract.test8241925.*;
 import static org.testng.Assert.assertEquals;
 import static test.jextract.test8241925.test8241925_h.*;
 
@@ -39,11 +38,11 @@
  * @run testng/othervm -Dforeign.restricted=permit LibTest8241925Test
  */
 public class LibTest8241925Test {
     @Test
     public void test() {
-        try (var scope = NativeAllocationScope.unboundedScope()) {
+        try (var scope = new CScope()) {
             var addr = Cint.allocate(12, scope);
             assertEquals(Cint.get(addr), 12);
             square(addr);
             assertEquals(Cint.get(addr), 144);
 
diff a/test/jdk/tools/jextract/test8244412/LibTest8244412Test.java b/test/jdk/tools/jextract/test8244412/LibTest8244412Test.java
--- a/test/jdk/tools/jextract/test8244412/LibTest8244412Test.java
+++ b/test/jdk/tools/jextract/test8244412/LibTest8244412Test.java
@@ -21,14 +21,14 @@
  * questions.
  */
 
 
 import jdk.incubator.foreign.MemoryAddress;
-import jdk.incubator.foreign.NativeAllocationScope;
 
 import org.testng.annotations.Test;
 import test.jextract.test8244412.Clong_long;
+import test.jextract.test8244412.CScope;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
 import static test.jextract.test8244412.test8244412_h.*;
 
 /*
@@ -41,11 +41,11 @@
  * @run testng/othervm -Dforeign.restricted=permit LibTest8244412Test
  */
 public class LibTest8244412Test {
     @Test
     public void test() {
-        try (var scope = NativeAllocationScope.unboundedScope()) {
+        try (var scope = new CScope()) {
             var addr = Cmysize_t.allocate(0L, scope);
             assertEquals(Cmysize_t.get(addr), 0L);
             Cmysize_t.set(addr, 13455566L);
             assertEquals(Cmysize_t.get(addr), 13455566L);
             assertTrue(Cmysize_t.sizeof() == Clong_long.sizeof());
diff a/test/jdk/tools/jextract/test8246341/LibTest8246341Test.java b/test/jdk/tools/jextract/test8246341/LibTest8246341Test.java
--- a/test/jdk/tools/jextract/test8246341/LibTest8246341Test.java
+++ b/test/jdk/tools/jextract/test8246341/LibTest8246341Test.java
@@ -20,11 +20,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
 
 import jdk.incubator.foreign.MemoryAddress;
-import jdk.incubator.foreign.NativeAllocationScope;
 import org.testng.annotations.Test;
 import test.jextract.test8246341.*;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
 import static test.jextract.test8246341.test8246341_h.*;
@@ -56,11 +55,11 @@
         assertTrue(callbackCalled[0]);
     }
 
     @Test
     public void testPointerAllocate() {
-        try (var scope = NativeAllocationScope.boundedScope(Cpointer.sizeof())) {
+        try (var scope = new CScope(Cpointer.sizeof())) {
             var addr = Cpointer.allocate(MemoryAddress.NULL, scope);
             fillin(addr);
             assertEquals(Cstring.toJavaString(Cpointer.get(addr)), "hello world");
         }
 
diff a/test/jdk/tools/jextract/test8246400/LibTest8246400Test.java b/test/jdk/tools/jextract/test8246400/LibTest8246400Test.java
--- a/test/jdk/tools/jextract/test8246400/LibTest8246400Test.java
+++ b/test/jdk/tools/jextract/test8246400/LibTest8246400Test.java
@@ -19,10 +19,11 @@
  * 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 jdk.incubator.foreign.MemoryAddress;
 import jdk.incubator.foreign.MemorySegment;
 import org.testng.annotations.Test;
 import test.jextract.test8246400.*;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
@@ -39,11 +40,12 @@
  * @run testng/othervm -Dforeign.restricted=permit LibTest8246400Test
  */
 public class LibTest8246400Test {
     @Test
     public void testSegmentRegister() {
-        MemorySegment sum = null, callback = null;
+        MemorySegment sum = null;
+        MemoryAddress callback = null;
         try (var scope = new CScope()) {
             var v1 = CVector.allocate(scope);
             CVector.x$set(v1, 1.0);
             CVector.y$set(v1, 0.0);
 
@@ -58,18 +60,17 @@
             assertEquals(CVector.y$get(sum.baseAddress()), 1.0, 0.1);
 
             callback = cosine_similarity$dot.allocate((a, b) -> {
                 return (CVector.x$get(a.baseAddress()) * CVector.x$get(b.baseAddress())) +
                     (CVector.y$get(a.baseAddress()) * CVector.y$get(b.baseAddress()));
-            });
-            scope.register(callback);
+            }, scope);
 
-            var value = cosine_similarity(v1.segment(), v2.segment(), callback.baseAddress());
+            var value = cosine_similarity(v1.segment(), v2.segment(), callback);
             assertEquals(value, 0.0, 0.1);
 
-            value = cosine_similarity(v1.segment(), v1.segment(), callback.baseAddress());
+            value = cosine_similarity(v1.segment(), v1.segment(), callback);
             assertEquals(value, 1.0, 0.1);
         }
         assertTrue(!sum.isAlive());
-        assertTrue(!callback.isAlive());
+        assertTrue(!callback.segment().isAlive());
     }
 }
