@SuppressWarnings({"PMD.AvoidCatchingGenericException", "PMD"})
final class {{ class_name }} {
private static final System.Logger LOGGER = System.getLogger({{ class_name }}.class.getName());
private static final Linker LINKER = Linker.nativeLinker();
private static SymbolLookup LIB;
private static final String NATIVES_RESOURCE_ROOT = "/natives";
private static final String LIBRARY_PATH_PROPERTY = "{{ lib_name }}.library.path";
private static final String LIBRARY_DIRECTORY_PROPERTY = "{{ lib_name }}.library.dir";
private static final String SKIP_BUNDLED_PROPERTY = "{{ lib_name }}.skipBundled";
private static final String LIBRARY_PATH_ENV = "{{ library_environment_prefix }}_LIB_PATH";
private static final String LIBRARY_DIRECTORY_ENV = "{{ library_environment_prefix }}_LIB_DIR";
private static final String SKIP_BUNDLED_ENV = "{{ library_environment_prefix }}_SKIP_BUNDLED";
private static final String[] REQUIRED_SYMBOLS = {
{% for symbol in required_symbols %}
"{{ symbol }}"{% if not loop.last %},{% endif +%}
{% endfor %}
};
private static final Object NATIVE_EXTRACT_LOCK = new Object();
private static String cachedExtractKey;
private static Path cachedExtractDir;
static {
Path loadedLibraryPath = loadNativeLibrary();
try {
Arena arena = Arena.ofShared();
// Try the loaded library path (for System.load() with absolute path)
if (loadedLibraryPath != null) {
try {
LIB = SymbolLookup.libraryLookup(loadedLibraryPath, arena);
} catch (RuntimeException | Error inner) {
// If Path variant fails, fallback to defaultLookup
LIB = LINKER.defaultLookup();
}
} else {
LIB = LINKER.defaultLookup();
}
validateRequiredSymbols(loadedLibraryPath);
} catch (RuntimeException | Error e) {
ExceptionInInitializerError error = new ExceptionInInitializerError(
"Failed to initialize library symbols: " + e.getMessage());
error.initCause(e);
throw error;
}
}
private static Path loadNativeLibrary() {
Path loadedLibraryPath = null;
String osName = System.getProperty("os.name", "").toLowerCase(java.util.Locale.ROOT);
String osArch = System.getProperty("os.arch", "").toLowerCase(java.util.Locale.ROOT);
String libName;
String libExt;
if (osName.contains("mac") || osName.contains("darwin")) {
libName = "lib{{ lib_name }}";
libExt = ".dylib";
} else if (osName.contains("win")) {
libName = "{{ lib_name }}";
libExt = ".dll";
} else {
libName = "lib{{ lib_name }}";
libExt = ".so";
}
String nativesRid = resolveNativesRid(osName, osArch);
String nativesDir = NATIVES_RESOURCE_ROOT + "/" + nativesRid;
String explicitPath = firstNonBlank(System.getProperty(LIBRARY_PATH_PROPERTY), System.getenv(LIBRARY_PATH_ENV));
if (explicitPath != null) {
return loadAbsolutePath(Paths.get(explicitPath));
}
String explicitDirectory = firstNonBlank(
System.getProperty(LIBRARY_DIRECTORY_PROPERTY),
System.getenv(LIBRARY_DIRECTORY_ENV));
if (explicitDirectory != null) {
return loadAbsolutePath(Paths.get(explicitDirectory, libName + libExt));
}
String skipBundledValue = firstNonBlank(
System.getProperty(SKIP_BUNDLED_PROPERTY),
System.getenv(SKIP_BUNDLED_ENV));
if (!Boolean.parseBoolean(skipBundledValue)) {
Path extracted = tryExtractAndLoadFromResources(nativesDir, libName, libExt);
if (extracted != null) {
return extracted;
}
}
try {
System.loadLibrary("{{ lib_name }}");
// Find the full path by searching java.library.path
Path libPath = findLoadedLibraryPath(libName, libExt);
if (libPath != null) {
loadedLibraryPath = libPath;
}
} catch (UnsatisfiedLinkError e) {
String msg = "Failed to load {{ lib_name }} native library. Expected resource: " + nativesDir + "/" + libName
+ libExt + " (RID: " + nativesRid + "). "
+ "Ensure the library is bundled in the JAR under natives/{os-arch}/, "
+ "place it on java.library.path, set -D" + LIBRARY_PATH_PROPERTY
+ "=/absolute/path, or set " + LIBRARY_PATH_ENV + ".";
UnsatisfiedLinkError out = new UnsatisfiedLinkError(msg + " Original error: " + e.getMessage());
out.initCause(e);
throw out;
}
return loadedLibraryPath;
}
private static String firstNonBlank(String preferred, String fallback) {
if (preferred != null && !preferred.isBlank()) {
return preferred;
}
if (fallback != null && !fallback.isBlank()) {
return fallback;
}
return null;
}
private static Path loadAbsolutePath(Path configuredPath) {
Path absolutePath = configuredPath.toAbsolutePath().normalize();
if (!Files.isRegularFile(absolutePath)) {
throw new UnsatisfiedLinkError("Configured native library does not exist: " + absolutePath);
}
System.load(absolutePath.toString());
return absolutePath;
}
private static void validateRequiredSymbols(Path loadedLibraryPath) {
List<String> missing = new ArrayList<>();
for (String symbol : REQUIRED_SYMBOLS) {
if (LIB.find(symbol).isEmpty() && LIB.find("_" + symbol).isEmpty()) {
missing.add(symbol);
}
}
if (missing.isEmpty()) {
return;
}
int exportedCount = REQUIRED_SYMBOLS.length - missing.size();
String loadedFrom = loadedLibraryPath == null
? "System.loadLibrary({{ lib_name }}) / java.library.path"
: loadedLibraryPath.toString();
throw new UnsatisfiedLinkError(
"The loaded {{ lib_name }} native library is stale relative to this binding: it exports "
+ exportedCount + " of " + REQUIRED_SYMBOLS.length + " required symbols. Missing: "
+ String.join(", ", missing) + ". Loaded from: " + loadedFrom
+ ". Rebuild the native library, point this binding at a current one with -D"
+ LIBRARY_PATH_PROPERTY + "=/absolute/path, or bypass bundled resources with -D"
+ SKIP_BUNDLED_PROPERTY + "=true.");
}
private static Path tryExtractAndLoadFromResources(String nativesDir, String libName, String libExt) {
String resourcePath = nativesDir + "/" + libName + libExt;
URL resource = NativeLib.class.getResource(resourcePath);
if (resource == null) {
return null;
}
try {
Path tempDir = extractOrReuseNativeDirectory(nativesDir);
Path libPath = tempDir.resolve(libName + libExt);
if (!Files.exists(libPath)) {
throw new UnsatisfiedLinkError("Missing extracted native library: " + libPath);
}
Path absPath = libPath.toAbsolutePath();
System.load(absPath.toString());
return absPath;
} catch (Exception | Error e) {
LOGGER.log(System.Logger.Level.WARNING, "Failed to extract and load native library from resources", e);
return null;
}
}
private static Path extractOrReuseNativeDirectory(String nativesDir) throws Exception {
URL location = NativeLib.class.getProtectionDomain().getCodeSource().getLocation();
if (location == null) {
throw new IllegalStateException("Missing code source location for {{ lib_name }} JAR");
}
Path codePath = Path.of(location.toURI());
String key = codePath.toAbsolutePath() + "::" + nativesDir;
synchronized (NATIVE_EXTRACT_LOCK) {
if (cachedExtractDir != null && key.equals(cachedExtractKey)) {
return cachedExtractDir;
}
Path tempDir = Files.createTempDirectory("{{ lib_name }}_native");
tempDir.toFile().deleteOnExit();
List<Path> extracted = extractNativeDirectory(codePath, nativesDir, tempDir);
if (extracted.isEmpty()) {
throw new IllegalStateException("No native files extracted from resources dir: " + nativesDir);
}
cachedExtractKey = key;
cachedExtractDir = tempDir;
return tempDir;
}
}
private static List<Path> extractNativeDirectory(Path codePath, String nativesDir, Path destDir) throws Exception {
if (!Files.exists(destDir) || !Files.isDirectory(destDir)) {
throw new IllegalArgumentException("Destination directory does not exist: " + destDir);
}
String prefix = nativesDir.startsWith("/") ? nativesDir.substring(1) : nativesDir;
if (!prefix.endsWith("/")) {
prefix = prefix + "/";
}
if (Files.isDirectory(codePath)) {
Path nativesPath = codePath.resolve(prefix);
if (!Files.exists(nativesPath) || !Files.isDirectory(nativesPath)) {
return List.of();
}
return copyDirectory(nativesPath, destDir);
}
List<Path> extracted = new ArrayList<>();
try (JarFile jar = new JarFile(codePath.toFile())) {
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String name = entry.getName();
if (!name.startsWith(prefix) || entry.isDirectory()) {
continue;
}
String relative = name.substring(prefix.length());
Path out = safeResolve(destDir, relative);
Files.createDirectories(out.getParent());
try (var in = jar.getInputStream(entry)) {
Files.copy(in, out, StandardCopyOption.REPLACE_EXISTING);
}
out.toFile().deleteOnExit();
extracted.add(out);
}
}
return extracted;
}
private static List<Path> copyDirectory(Path srcDir, Path destDir) throws Exception {
List<Path> copied = new ArrayList<>();
try (var paths = Files.walk(srcDir)) {
for (Path src : (Iterable<Path>) paths::iterator) {
if (Files.isDirectory(src)) {
continue;
}
Path relative = srcDir.relativize(src);
Path out = safeResolve(destDir, relative.toString());
Files.createDirectories(out.getParent());
Files.copy(src, out, StandardCopyOption.REPLACE_EXISTING);
out.toFile().deleteOnExit();
copied.add(out);
}
}
return copied;
}
private static Path safeResolve(Path destDir, String relative) throws Exception {
Path normalizedDest = destDir.toAbsolutePath().normalize();
Path out = normalizedDest.resolve(relative).normalize();
if (!out.startsWith(normalizedDest)) {
throw new SecurityException("Blocked extracting native file outside destination directory: " + relative);
}
return out;
}
private static String resolveNativesRid(String osName, String osArch) {
// Classifier names match go_java_platform(): `linux-aarch64`, `macos-arm64`,
// `windows-x86_64`, etc. macOS distinguishes arm64 (ARM-based), while other
// platforms use aarch64. Align with src/publish/platform.rs::go_java_platform().
boolean isMac = osName.contains("mac") || osName.contains("darwin");
boolean isWindows = osName.contains("win");
String arch;
if (osArch.contains("aarch64") || osArch.contains("arm64")) {
// macOS uses "arm64" for aarch64; Linux uses "aarch64"
arch = isMac ? "arm64" : "aarch64";
} else if (osArch.contains("x86_64") || osArch.contains("amd64")) {
arch = "x86_64";
} else {
arch = osArch.replaceAll("[^a-z0-9_]+", "");
}
String os;
if (isMac) {
os = "macos";
} else if (isWindows) {
os = "windows";
} else {
os = "linux";
}
return os + "-" + arch;
}
private static Path findLoadedLibraryPath(String fullLibName, String libExt) {
// Search java.library.path for the library file
String javaLibPath = System.getProperty("java.library.path");
if (javaLibPath != null) {
for (String path : javaLibPath.split(File.pathSeparator)) {
Path libPath = Paths.get(path, fullLibName + libExt);
if (Files.exists(libPath)) {
try {
return libPath.toRealPath();
} catch (java.io.IOException e) {
return libPath.toAbsolutePath();
}
}
}
}
// Library not found in java.library.path
return null;
}
{% for function_handle in function_handles %}
{{ function_handle }}
{% endfor %}
static final MethodHandle {{ prefix_upper }}_LAST_ERROR_CODE = LINKER.downcallHandle(
LIB.find("{{ prefix }}_last_error_code").orElse(null),
FunctionDescriptor.of(ValueLayout.JAVA_LONG)
);
static final MethodHandle {{ prefix_upper }}_LAST_ERROR_CONTEXT = LINKER.downcallHandle(
LIB.find("{{ prefix }}_last_error_context").orElse(null),
FunctionDescriptor.of(ValueLayout.ADDRESS)
);
{% for accessor_handle in accessor_handles %}
{{ accessor_handle }}
{% endfor %}
{% for builder_handle in builder_handles %}
{{ builder_handle }}
{% endfor %}
{% for trait_handle in trait_handles %}
{{ trait_handle }}
{% endfor %}
{% if visitor_handles %}
{{ visitor_handles }}
{% endif %}
}