丝束代码提交

This commit is contained in:
cwchen 2025-11-19 15:06:16 +08:00
parent 18b59bcaf7
commit 1d639cd3fa
1 changed files with 258 additions and 0 deletions

View File

@ -0,0 +1,258 @@
package com.bonus.boot.manager.manager.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
/**
* Sigar 库加载器
* 优先使用 yml 配置的路径如果配置路径不存在则从 classpath 加载
*/
@Component
@Order(Integer.MIN_VALUE)
public class SigarLibraryLoader {
private static volatile boolean libraryLoaded = false;
private static final Object loadLock = new Object();
@Autowired(required = false)
private Environment environment;
/**
* 静态初始化块在类加载时就尝试加载库
* 这确保在 Sigar 类被加载之前库已经加载
* 如果失败静默处理因为配置路径在静态初始化时不可用后续的 @PostConstruct 会重试
*/
static {
try {
loadSigarNativeLibraryStatic();
} catch (Exception e) {
// 静默处理因为配置路径在静态初始化时不可用
// 后续的 @PostConstruct 方法会使用配置路径重试
// 不抛出异常允许类加载继续
}
}
/**
* Bean 初始化时加载库
* 此时 Spring 环境已初始化可以使用配置的路径
* 这是主要的加载方式因为配置路径在静态初始化时不可用
*/
@PostConstruct
public void loadLibrary() {
if (!libraryLoaded) {
synchronized (loadLock) {
if (!libraryLoaded) {
try {
doLoadLibrary();
libraryLoaded = true;
System.out.println("Sigar library loaded successfully");
} catch (Exception e) {
System.err.println("ERROR: Failed to load Sigar library: " + e.getMessage());
e.printStackTrace();
// 不设置 libraryLoaded = true允许后续重试
}
}
}
}
}
/**
* 静态方法在类加载时加载库
*/
private static void loadSigarNativeLibraryStatic() {
if (!libraryLoaded) {
synchronized (loadLock) {
if (!libraryLoaded) {
doLoadLibraryStatic();
libraryLoaded = true;
}
}
}
}
/**
* 静态方法实际加载库的逻辑仅从 classpath因为配置不可用
*/
private static void doLoadLibraryStatic() {
try {
String osName = System.getProperty("os.name").toLowerCase();
String arch = System.getProperty("os.arch").toLowerCase();
String libraryName = getLibraryName(osName, arch);
loadFromClasspathStatic(libraryName);
} catch (Exception e) {
throw new RuntimeException("Failed to load Sigar native library in static initializer", e);
}
}
/**
* 获取库文件名根据操作系统和架构
*/
private static String getLibraryName(String osName, String arch) {
if (osName.contains("win")) {
return arch.contains("64") ? "sigar-amd64-winnt.dll" : "sigar-x86-winnt.dll";
} else if (osName.contains("linux")) {
return arch.contains("64") ? "libsigar-amd64-linux.so" : "libsigar-x86-linux.so";
} else if (osName.contains("mac")) {
return "libsigar-universal64-macosx.dylib";
} else {
throw new UnsupportedOperationException("Unsupported operating system: " + osName);
}
}
/**
* 静态方法 classpath 加载库
* 尝试多个类加载器以确保能找到资源
*/
private static void loadFromClasspathStatic(String libraryName) {
InputStream inputStream = null;
// 尝试多个类加载器
ClassLoader[] classLoaders = new ClassLoader[] {
SigarLibraryLoader.class.getClassLoader(),
Thread.currentThread().getContextClassLoader(),
ClassLoader.getSystemClassLoader()
};
for (ClassLoader classLoader : classLoaders) {
if (classLoader != null) {
try {
inputStream = classLoader.getResourceAsStream(libraryName);
if (inputStream != null) {
System.out.println("Found library using classLoader: " + classLoader.getClass().getName());
break;
}
} catch (Exception e) {
// 继续尝试下一个类加载器
}
}
}
if (inputStream == null) {
// 尝试使用绝对路径 resources 根目录
for (ClassLoader classLoader : classLoaders) {
if (classLoader != null) {
try {
inputStream = classLoader.getResourceAsStream("/" + libraryName);
if (inputStream != null) {
System.out.println("Found library using absolute path with classLoader: " + classLoader.getClass().getName());
break;
}
} catch (Exception e) {
// 继续尝试下一个类加载器
}
}
}
}
if (inputStream == null) {
throw new RuntimeException("Sigar native library not found in classpath: " + libraryName +
". Please ensure the DLL file is in src/main/resources/ directory.");
}
try {
File tempFile = File.createTempFile("sigar", getFileExtension(libraryName));
tempFile.deleteOnExit();
Files.copy(inputStream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
inputStream.close();
System.load(tempFile.getAbsolutePath());
System.out.println("Successfully loaded Sigar library from classpath (static): " + libraryName + " -> " + tempFile.getAbsolutePath());
} catch (Exception e) {
if (inputStream != null) {
try {
inputStream.close();
} catch (Exception ignored) {
}
}
throw new RuntimeException("Failed to load Sigar library from classpath: " + libraryName, e);
}
}
/**
* 获取文件扩展名
*/
private static String getFileExtension(String filename) {
int lastDot = filename.lastIndexOf('.');
return lastDot == -1 ? "" : filename.substring(lastDot);
}
/**
* 实际加载库的逻辑实例方法此时 Spring 环境已初始化
* 优先使用配置的路径如果配置路径不存在则从 classpath 加载
*/
private void doLoadLibrary() {
try {
String osName = System.getProperty("os.name").toLowerCase();
String arch = System.getProperty("os.arch").toLowerCase();
String libraryName = getLibraryName(osName, arch);
String configuredPath = getConfiguredLibraryPath(osName, arch);
// 优先使用配置的路径
if (configuredPath != null && !configuredPath.trim().isEmpty()) {
File libraryFile = new File(configuredPath);
if (libraryFile.exists()) {
System.load(configuredPath);
System.out.println("Successfully loaded Sigar library from configured path: " + configuredPath);
return;
} else {
System.err.println("Configured Sigar library path not found: " + configuredPath + ", falling back to classpath");
}
}
// 备用方案 classpath 加载
loadFromClasspath(libraryName);
} catch (Exception e) {
throw new RuntimeException("Failed to load Sigar native library", e);
}
}
/**
* 从配置中获取库文件路径
*/
private String getConfiguredLibraryPath(String osName, String arch) {
if (environment == null) {
return null;
}
String pathKey;
if (osName.contains("win")) {
pathKey = arch.contains("64") ? "sigar.library-paths.windows64" : "sigar.library-paths.windows32";
} else if (osName.contains("linux")) {
pathKey = arch.contains("64") ? "sigar.library-paths.linux64" : "sigar.library-paths.linux32";
} else if (osName.contains("mac")) {
pathKey = "sigar.library-paths.macos";
} else {
return null;
}
return environment.getProperty(pathKey);
}
/**
* classpath 加载库实例方法复用静态方法的逻辑
*/
private void loadFromClasspath(String libraryName) {
loadFromClasspathStatic(libraryName);
}
/**
* 检查库是否已加载
*/
public static boolean isLibraryLoaded() {
return libraryLoaded;
}
}