我们的许多软件都存在Hook线程的一个校验机制,其目的是校验进程是否已经启动,防止进程重复启动;Hook线程又称为钩子线程,在jvm退出的时候会执行Hook线程;比如mysql在启动的时候就会创建一个.lock文件,用.lock文件校验进程是否启动;Hook线程除了防止重新启动进程之外,还可以用做资源释放;尽量不要在Hook线程中进行复杂的操作以免影响性能;
在linux上要注意的是执行权限,按照文件的权限设计permission字符串位数必须是9位,每前三位都是rwx,分别代表可读,可写。可执行;前三位代表文件的属主,中三位代表文件的属组,后三位代表其他用户对此文件的权限,有兴趣的朋友可以点源码进去看看,注意不同的系统路径不一样;
/**
* @Author lsc
* @Description <p> HOOK线程 </p>
* @Date 2019/11/3 14:54
*/
public class Hook {
// 文件路径
private static final String HOOK_PATH = "C:\\mydata\\generator";
// 文件名称
private static final String HOOK_FILE = ".lock";
// linux执行权限
private static final String PERMS = "rwx------";
public static void main(String[] args) {
// 1 检查程序是否在运行,是异常提示,否创建lock文件
checkRunningForWindows();
// 2 注入hook线程,程序退出的时候执行删除lock文件
registerHook();
// 3 模拟程序在运行
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// windows系统上
private static void checkRunningForWindows(){
// 获得path
Path path = getPath();
// lock文件如果已经存在则异常
if (path.toFile().exists())
throw new RuntimeException("程序已经在运行");
// lock文件不存在则创建
try {
path.toFile().createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
// linux系统上检查程序是否在运行
private static void checkRunningForLinux(){
// 获得path
Path path = getPath();
// lock文件如果已经存在则异常
if (path.toFile().exists())
throw new RuntimeException("程序已经在运行");
// lock文件不存在则创建
Set<PosixFilePermission> posixFilePermissions = PosixFilePermissions.fromString(PERMS);
try {
Files.createFile(path, PosixFilePermissions.asFileAttribute(posixFilePermissions));
} catch (IOException e) {
e.printStackTrace();
}
}
// 注入hook
private static void registerHook(){
Runtime.getRuntime().addShutdownHook(new Thread( ()-> {
// 退出提示
System.out.println("程序即将退出");
// 删除lock文件
deleteLock();
}));
}
// 删除lock文件
private static void deleteLock(){
// 获得path
Path path = getPath();
// 删除lock文件
path.toFile().delete();
}
// 获得Path
private static Path getPath(){
// 文件路劲拼接返回一个Path对象
Path path = Paths.get(HOOK_PATH, HOOK_FILE);
return path;
}
}