丝束代码提交
This commit is contained in:
parent
18b59bcaf7
commit
1d639cd3fa
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue