Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Jni And Ffm

ASecurity

Crossing into native code: JNI call overhead, critical sections and what they block, the FFM downcall and upcall path, `Linker` and method handles, why a native frame pins a virtual thread, and measuring the boundary cost. Use when a native call sits inside a tight loop, when someone proposes migrating JNI to Panama to fix pinning, when `Linker.Option.critical()` is applied without a measured duration, when `jdk.VirtualThreadPinned` events point at a `native` method or `MethodHandle.invokeExa...

2 stars
0 votes
0 copies
0 views
Added 9/19/2026
developmentgojavatestingapi

Works with

api

Security Analysis

A100/100

Scanned 9/19/2026

Install to Claude Code

$npx -y skills add robsonkades/agent-skills --skill jni-and-ffm --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Jni And Ffm?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Jni And Ffm
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/robsonkades-jni-and-ffm/badge)](https://www.skillsdirectory.com/skills/robsonkades-jni-and-ffm)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: jni-and-ffm
description: >
  Crossing into native code: JNI call overhead, critical sections and what they block, the
  FFM downcall and upcall path, `Linker` and method handles, why a native frame pins a
  virtual thread, and measuring the boundary cost. Use when a native call sits inside a
  tight loop, when someone proposes migrating JNI to Panama to fix pinning, when
  `Linker.Option.critical()` is applied without a measured duration, when
  `jdk.VirtualThreadPinned` events point at a `native` method or `MethodHandle.invokeExact`,
  when `WARNING: A restricted method ... has been called` appears after a JDK upgrade, when
  a runbook still references `-Djdk.tracePinnedThreads` or `--enable-preview` for FFM, when
  `jextract` is assumed to ship with the JDK, when a downcall fails with
  `WrongThreadException` on a confined arena, or when `GCLocker Initiated GC` appears as a
  cause in the GC log. Does not cover holding native memory (off-heap-memory), pinning as
  scheduling (virtual-threads-internals), or the native memory budget (jvm-memory-regions).
---

# JNI and the FFM Boundary

## Purpose

Reason about the cost and the risk of a call that leaves the JVM. The boundary has three
independent cost components — the thread-state transition, marshaling, and verification —
and almost every wrong decision here comes from collapsing them into one number, or from
treating an option that addresses one of them as if it addressed another.

The failure this prevents is the migration that fixes nothing. FFM can improve safety and
binding ergonomics without making a blocking foreign call unmountable. A native/foreign
frame prevents virtual-thread unmounting in current HotSpot; `critical()` is a narrowly
constrained optimization hint, not an asynchronous-native-call mechanism.

## Workflow

Inspect the project's compiler/toolchain, runtime image, native library and target ABI first.
The final FFM examples require JDK 22+; the reference observations use HotSpot 25.0.3.
Applying this skill does not authorize an upgrade or removal of preview flags used by other features.
Reuse the supplied workload, profiles and binding contracts; ask only for missing facts that
could change safety or the decision. Keep an adequate audited binding/execution path when it
meets the relevant budget. A native frame alone is not a reason to redesign it.

1. **Specify the native contract first.** ABI, ownership, lifetime, thread affinity,
   reentrancy/upcalls, cancellation, error channel, blocking behavior and worst-case duration
   decide correctness. API choice also affects checks, maintainability and deployment.
2. **Consider batching when fixed cost is material:** one transition for the whole batch,
   with the work loop inside native code. Compare retaining individual calls against the
   added latency, ownership and partial-failure contract; a longer batch can occupy a carrier
   longer and does not enable unmounting.
3. **Apply the documented `critical()` preconditions.** The function must be extremely short
   in every case and must not call back into Java. Prove bounded non-blocking behavior and
   validate useful benefit if optimizing; observed percentiles cannot prove the all-cases
   contract. Do not invent a universal microsecond cutoff. See
   `references/critical-and-decision-matrix.md`.
4. **Diagnose consequential carrier capture using relevant evidence.** `jdk.VirtualThreadPinned` reports a
   virtual thread attempting a blocking operation while pinned; it may not report C code
   simply blocking inside a native frame. Correlate available JFR, thread dumps, wall/native
   profiles, call duration and carrier capacity; collect only what resolves a material gap.
5. **When occupancy or failure isolation warrants a change, compare:** a bounded dedicated platform-thread
   pool, an asynchronous/non-blocking native API, process isolation or a Java alternative.
   Size/admit the pool from latency, concurrency, resource limits and overload policy, then
   let the virtual thread await the `Future`.
   Waiting on a `Future` is ordinary Java and unmounts normally. Allocate the call's
   segments on the pool thread, inside the task: a confined-arena segment created on the
   caller's thread fails the first downcall with `WrongThreadException`. See
   `references/arenas-upcalls-and-gc.md`.
6. **Declare native access explicitly in production.** `--enable-native-access=<module>` or
   `ALL-UNNAMED`, per module, rather than relying on the current warn-only default.
7. **Match verification to the proposed change.** For an overhead question, JMH can compare
   relevant JNI/plain FFM/eligible `critical` paths for the same function; no cross-API
   benchmark is required to retain an adequate binding. `-prof gc` measures Java allocation, not native
   copy volume; instrument bytes/copies or inspect the native implementation separately.

Return the boundary contract, observed evidence versus hypotheses, justified change or
no-change decision, and actual validation versus remaining checks. A measured boundary-cost
change alone does not establish service benefit.

## Rules

- Current virtual-thread implementations cannot unmount across a native method or foreign
  function frame. JNI and FFM therefore both capture a carrier for blocking work; exact event
  visibility and stub behavior differ, so diagnose rather than assuming identical telemetry.
- `Linker.Option.isTrivial()` does not exist in the finalised FFM API. The final name, since
  JEP 454 (JDK 22 GA), is `Linker.Option.critical(boolean allowHeapAccess)`.
- `critical()` is an API hint that permits implementation optimizations valid only for an
  extremely short, no-upcall function. HotSpot versions may omit normal transitions/checks,
  increasing safepoint and crash risk if preconditions are violated. Do not encode a specific
  `_thread_in_native` implementation as the portable contract.
- Read `critical` as "critical section", not as "trivial" or "fast and always safe". That
  misreading is the most common error with this API.
- `critical(true)` permits heap-backed segments as address arguments for the call. It is
  conceptually related to JNI critical access but not an exact equivalence: JNI may return a
  copy or pin, and FFM/collector implementation can evolve. Treat the address as temporary,
  obey critical-section restrictions, and observe collector/safepoint behavior on the
  deployed JDK. See
  `references/arenas-upcalls-and-gc.md`.
- An exception escaping an upcall target terminates the JVM, per the `Linker` contract.
  Ensure the target and its error handler cannot let `Throwable` escape. Translate failures
  through the native API's supported return/error-state protocol; do not invent a return
  code for a callback whose signature has none. No
  upcall may run from a `critical` downcall. See `references/arenas-upcalls-and-gc.md`.
- When blocking native calls exceed the workload's occupancy or failure budget, consider
  bounded platform-thread isolation, a truly asynchronous native interface, process isolation
  or replacement. `critical()` and a JNI-to-FFM rewrite
  alone do not make the call unmountable.
- `-Djdk.tracePinnedThreads` was removed in JDK 24. Use `jdk.VirtualThreadPinned` for Java
  blocking attempts while pinned, plus wall/native profiles and carrier/call metrics for time
  spent blocking inside native code.
- JEP 472 brought JNI loading under the native-access restrictions already used by FFM in
  JDK 24. On JDK 24/25, unauthorized restricted use warns by default and can be configured;
  future policy is intended to deny. Declare `--enable-native-access` for the responsible
  modules and test with the exact release's `--illegal-native-access` policy.
- Warnings are associated with restricted load/link operations such as native library loads,
  downcall/upcall creation and library lookup, typically once per module—not each segment
  read. Library loading and FFM restricted calls use the caller module; JNI method binding
  uses the module declaring the native method. Generated bindings do not inherit an exemption.
- FFM is final since JDK 22 and does not itself require `--enable-preview` there. Older
  preview APIs differ; preserve flags needed by other project features.
- `jextract` is an OpenJDK project/tool distributed separately from the standard JDK; vendor
  bundles can differ. Pin its version/target ABI and review generated ownership/error policy.
- Close confined/shared arenas according to the native ownership boundary. Automatic arenas
  need a strongly reachable Java owner while native code retains pointers. The global arena
  remains alive for the JVM lifetime, trading simple retention for no early reclamation.
  Neither kind is manually closeable. Before freeing a retained upcall stub or its state,
  stop new callbacks and establish completion of in-flight callbacks under the library's
  unregister/quiescence contract; closing the arena does not unregister a native pointer.
  JNI critical/element APIs must be released on every path.
- Do not assume FFM is faster than JNI. Descriptor shape, checks, marshaling, JIT compilation,
  native work and copies dominate differently. Benchmark the same ABI/function/data path and
  retain safety and maintainability in the decision.
- An aggregate CPU overhead calculation is not a tail-latency prediction without an explicit
  queueing model connecting the two.
- A `FunctionDescriptor` is executable ABI metadata. Wrong C width, signedness, struct layout,
  variadic boundary, calling convention or callback lifetime can corrupt memory or crash the
  JVM despite Java's static types. Test against headers on every target platform.
- Native cancellation is cooperative: cancelling a `Future` or interrupting the Java caller
  does not reliably stop C code. Define timeout, abandonment, resource ownership and late
  completion behavior at the boundary.

## References

- [Critical, and choosing an interop approach](references/critical-and-decision-matrix.md) —
  the overhead components per call type, the thread-state and safepoint table, the measurable
  eligibility criteria for `critical()`, and the JNI/Panama/jextract/JNA decision matrix. Read
  before choosing an interop API or approving a `critical()` call.
- [Arenas, upcalls and the collector](references/arenas-upcalls-and-gc.md) — arena kinds at
  the interop boundary (confined handoff, shared close, stub lifetime, automatic arenas),
  the upcall contracts and cost order, `captureCallState` for `errno` and
  `firstVariadicArg`, what a critical region does to each collector, and the testing
  levers. Read when a downcall fails with `WrongThreadException` or `Already closed`,
  when designing a callback API, when a native function sets `errno` or is variadic, or
  when `GCLocker Initiated GC` appears in a GC log.
- [Detecting and mitigating native pinning](references/pinning-and-native-access.md) — the JFR
  and async-profiler recipes for pinning of native origin, the dedicated-pool mitigation
  pattern, the JEP 472 warning surface, `jextract` usage, and the operational checklists. Read
  during an incident, or before a service that makes native calls goes to production.

Attribution

robsonkadesrobsonkades
View sourceMore from robsonkades →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

281612 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2132 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

9881 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →