The native Keyword in Java - Quiz

Total: 6 questions

1. 

What does the native keyword mean in Java?

native is a method modifier saying that the body of the method is implemented outside the JVM — in a compiled library (.dll, .so, .dylib) written in a language with a C-compatible ABI, usually C or C++, but Rust, Fortran or assembly work just as well. The Java side carries only the signature: there is no body and the declaration ends with a semicolon, as in public native int hashCode();

The keyword itself compiles nothing and links nothing. It does exactly one job: it lets a method be declared without a body and marks it as "the implementation arrives from elsewhere". Connecting that declaration to a real function at runtime is the job of JNI (Java Native Interface). People reach for native to use operating-system features the standard library does not expose, to reuse mature C/C++ libraries (codecs, cryptography, drivers) and inside the JDK itself.

2. 

How does JNI find the implementation of a native method, and what has to match?

Three things have to line up.

1. The library is loaded. Normally in a static initializer: System.loadLibrary("demo") searches java.library.path, while System.load("/absolute/path/libdemo.so") takes a full path. Do not write the lib prefix or the file extension inside loadLibrary() — the JVM adds the platform-specific ones itself.

2. The function name matches. The symbol is built by a strict rule: Java_ + the package with dots replaced by underscores + _ + the class name + _ + the method name. For com.example.Demo.sum() that is Java_com_example_Demo_sum.

3. The signature matches. The first parameter of the C function is always JNIEnv*; the second is jobject for an instance method or jclass for a static one; then come the declared parameters in JNI types (jint, jlong, jstring).

You never spell those names out by hand: the compiler generates the header with javac -h . Demo.java (the flag exists since JDK 8). The separate javah tool was deprecated in JDK 9 and removed in JDK 10.

3. 

Which modifiers can native be combined with, and where is native illegal?

Allowed: static (the C function then receives jclass instead of jobject as its second argument), synchronized (the monitor is acquired before control enters the native code), final and any access modifier — private, public, protected. A native method may declare throws and throw ordinary Java exceptions (the native side raises them through ThrowNew), and it takes part in reflection: Modifier.isNative(m.getModifiers()).

Illegal:

  • native with a body — native methods cannot have a body; the declaration ends with ;;
  • native + abstractillegal combination of modifiers: both mean "no body here", but abstract promises an implementation in a subclass and native promises one in a library;
  • native on a field or a class — modifier native not allowed here; the keyword applies to methods only;
  • native on a constructor — move the native initialization into a separate native method and call it from the constructor;
  • native in an interface — interface methods are either abstract or default/static with a Java body.
4. 

Can a native method be overridden by a regular Java method in a subclass?

Yes. Inheritance does not care where the implementation lives: native is not part of the method signature, so it plays no role in overriding. A native method can be overridden by a plain Java method, and a plain method of a superclass can be overridden by a native one.

The clearest example ships with the JDK: Object.hashCode() is declared native, while String overrides it with pure Java code. Reflection confirms it in two lines:

System.out.println(Modifier.isNative(
        Object.class.getDeclaredMethod("hashCode").getModifiers())); // true
System.out.println(Modifier.isNative(
        String.class.getDeclaredMethod("hashCode").getModifiers())); // false
5. 

Is a native method faster than a regular Java method, and where does native appear in the standard library?

No — native does not mean faster. Every crossing from Java into native code and back has a price: the JVM fixes up thread state, the JIT loses optimizations such as inlining across the call, and objects have to be reached through JNI functions. A small method called in a tight loop is frequently slower after being moved to C than the Java version it replaced.

At the same time you call native methods every day: Object.hashCode(), Object.getClass(), Object.clone(), System.arraycopy(), System.currentTimeMillis(), System.nanoTime(), Thread.currentThread(), Runtime.availableProcessors().

Many of them are annotated @IntrinsicCandidate in the JDK sources, which allows the HotSpot JIT to replace the call with hand-written machine code (an intrinsic) right at the call site. So in hot code System.arraycopy() or Math.sqrt() never travel the JNI path at all — here native only records the fact that there is no Java body.

6. 

What replaces JNI and native methods in modern Java?

The Foreign Function & Memory API in the java.lang.foreign package (Project Panama). It went through preview rounds in JDK 19—21 and was finalized in JDK 22 (JEP 454). It calls a function from a native library without a single line of C:

Linker linker = Linker.nativeLinker();
MethodHandle strlen = linker.downcallHandle(
        linker.defaultLookup().find("strlen").orElseThrow(),
        FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS));

try (Arena arena = Arena.ofConfined()) {
    MemorySegment text = arena.allocateFrom("Hello, native!");
    System.out.println((long) strlen.invoke(text)); // 14
}

Compared with JNI: no C shim and no per-platform .so/.dll build of your own; many failures surface as Java exceptions instead of crashing the whole JVM; memory is released deterministically through Arena.

There is no urgency to rewrite existing JNI code — it is supported, and the native modifier remains part of the language. But since JDK 24 (JEP 472) both JNI and FFM count as restricted operations: the JVM prints a warning when a native library is loaded and when native methods are bound, silenced with --enable-native-access=ALL-UNNAMED.

Page 1 of 1