# Test PAC/BTI support with Oracle JDK

## In this learning path

- [Introduction](https://learn.arm.com/learning-paths/servers-and-cloud-computing/openjdk-pacbti-gcp/)
- [Learn about PAC/BTI security features and OpenJDK support](https://learn.arm.com/learning-paths/servers-and-cloud-computing/openjdk-pacbti-gcp/background/)
- [Create a Google Cloud C4A instance](https://learn.arm.com/learning-paths/servers-and-cloud-computing/openjdk-pacbti-gcp/instance/)
- [Test PAC/BTI support with SUSE OpenJDK](https://learn.arm.com/learning-paths/servers-and-cloud-computing/openjdk-pacbti-gcp/jvm-testing/)
- [Test PAC/BTI support with Oracle JDK](https://learn.arm.com/learning-paths/servers-and-cloud-computing/openjdk-pacbti-gcp/jvm-testing-2/)
- [Next Steps](https://learn.arm.com/learning-paths/servers-and-cloud-computing/openjdk-pacbti-gcp/_next-steps/)

## Install the Oracle JDK
The SUSE-packaged OpenJDK 17 confirmed that the C4A platform exposes PAC and BTI, but its JIT compiler doesn’t emit PAC/BTI instructions. Oracle’s JDK 21 for Linux/AArch64 is built with `--enable-branch-protection`, so the JIT compiler generates PAC/BTI instructions in compiled Java code.

Download and install Oracle JDK 21:
```
curl -LO https://download.oracle.com/java/21/latest/jdk-21_linux-aarch64_bin.tar.gz
tar xzf jdk-21_linux-aarch64_bin.tar.gz
```

Confirm the installation:
```
./jdk-21.0.11/bin/java --version
```

> The minor version number in the directory name (e.g., `21.0.11`) may differ depending on when you download. Check the extracted directory name with `ls` and adjust the path accordingly.

The output is similar to:
```
__output__ java version 21.0.11 2026-04-21 LTS
__output__ Java(TM) SE Runtime Environment (build 21.0.11+9-LTS-211)
__output__ Java HotSpot(TM) 64-Bit Server VM (build 21.0.11+9-LTS-211, mixed mode, sharing)
```

## Run the PAC/BTI test with the Oracle JDK
Use the same `test-pacbti.sh` script from the previous step, pointing it at the Oracle JDK:
```
JAVA=./jdk-21.0.11/bin/java ./test-pacbti.sh
```

This runs the same three checks (flag visibility, branch protection flag exercise, and the in-JVM auxv probe) against the Oracle JDK instead of the system JDK.

The output is similar to:
```
__output__ === OpenJDK JVM PAC/BTI platform exercise ===
__output__ Using java: ./jdk-21.0.11/bin/java

__output__ --- java -version ---
__output__ java version "21.0.11" 2026-04-21 LTS
__output__ Java(TM) SE Runtime Environment (build 21.0.11+9-LTS-211)
__output__ Java HotSpot(TM) 64-Bit Server VM (build 21.0.11+9-LTS-211, mixed mode, sharing)

__output__ --- JVM branch-protection flag visibility check ---
__output__ This is informational.
    ccstr UseBranchProtection                      = none                                 {ARCH product} {default}

__output__ --- Optional runtime flag exercise: -XX:UseBranchProtection=standard ---
__output__ This should be accepted by branch-protection-aware OpenJDK builds; older builds may reject it.
__output__ Accepted: -XX:UseBranchProtection=standard

__output__ --- Running in-JVM auxv probe ---
__output__ === JVM AArch64 PAC/BTI Probe ===
__output__ Process PID          : 4916
__output__ Java VM              : Java HotSpot(TM) 64-Bit Server VM
__output__ Java VM version      : 21.0.11+9-LTS-211
__output__ Java runtime version : 21.0.11+9-LTS-211
__output__ os.name              : Linux
__output__ os.arch              : aarch64

__output__ AT_HWCAP             : 0x00000000efffffff
__output__ AT_HWCAP2            : 0x000000000003f3ff

__output__ Decoded AArch64 features visible to this JVM process:
  HWCAP_PACA         : YES
  HWCAP_PACG         : YES
  PAC present        : YES
  HWCAP2_BTI         : YES

__output__ FINAL RESULT: POSITIVE
__output__ Meaning     : The JVM is executing on Linux/AArch64 with PAC and BTI exposed to userspace.

__output__ ===========================================
__output__   SUMMARY
__output__ ===========================================
__output__   Platform PAC/BTI (hardware + kernel): YES
__output__   JVM JIT PAC/BTI support:              YES

__output__   FULL PAC/BTI SUPPORT
__output__   The platform exposes PAC/BTI and this JVM can use it in JIT-compiled code.
__output__   Use -XX:UseBranchProtection=standard to enable it.
__output__ ===========================================
```

## Interpret the results
The Oracle JDK 21 output shows three key improvements over the SUSE OpenJDK 17:
- **`UseBranchProtection` flag is visible.** The JVM exposes this as a configurable option, confirming it was built with branch protection support.
- **`-XX:UseBranchProtection=standard` is accepted.** The JIT compiler can be told to emit PAC/BTI instructions in compiled Java code.
- **SUMMARY shows FULL PAC/BTI SUPPORT.** The platform exposes PAC/BTI and the JVM JIT can use it.

The default value of `UseBranchProtection = none` means the JIT doesn’t emit PAC/BTI instructions unless you opt in with `-XX:UseBranchProtection=standard`. This gives you control over whether to enable the feature for your workloads.

| Layer                  | SUSE OpenJDK 17        | Oracle JDK 21                                             |
|------------------------|------------------------|-----------------------------------------------------------|
| Hardware + kernel      | ✅ PAC/BTI exposed      | ✅ PAC/BTI exposed                                        |
| OS and native libraries | ✅ Protected            | ✅ Protected                                              |
| JVM JIT compiler       | ❌ Not enabled          | ✅ Available (opt-in via `-XX:UseBranchProtection=standard`) |

✅ Full PAC/BTI protection achieved!

To run your Java application with full PAC/BTI JIT protection:
```
./jdk-21.0.11/bin/java -XX:UseBranchProtection=standard -jar your-application.jar
```

## What you’ve learned
You now have a complete picture of PAC/BTI support for Java on Google Cloud C4A:
- The C4A platform (Arm Neoverse-V2) exposes PAC and BTI to userspace.
- The SUSE-packaged OpenJDK 17 cannot use these features in JIT-compiled code.
- Oracle JDK 21 supports PAC/BTI in the JIT compiler and lets you enable it with a runtime flag.

With `-XX:UseBranchProtection=standard`, the JIT compiler signs return addresses with PAC and marks branch targets with BTI in dynamically compiled Java methods. This extends hardware-enforced control-flow integrity from the OS and native libraries into your Java application code.
