惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
酷 壳 – CoolShell
酷 壳 – CoolShell
Google Online Security Blog
Google Online Security Blog
Engineering at Meta
Engineering at Meta
U
Unit 42
Security Latest
Security Latest
G
Google Developers Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
D
Docker
T
Tailwind CSS Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
云风的 BLOG
云风的 BLOG
Hugging Face - Blog
Hugging Face - Blog
M
MIT News - Artificial intelligence
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
MongoDB | Blog
MongoDB | Blog
H
Help Net Security
Stack Overflow Blog
Stack Overflow Blog
C
Check Point Blog
S
Security Affairs
T
The Exploit Database - CXSecurity.com
S
SegmentFault 最新的问题
N
News and Events Feed by Topic
The GitHub Blog
The GitHub Blog
Apple Machine Learning Research
Apple Machine Learning Research
S
Securelist
IT之家
IT之家
P
Palo Alto Networks Blog
D
DataBreaches.Net
Help Net Security
Help Net Security
N
Netflix TechBlog - Medium
B
Blog RSS Feed
AWS News Blog
AWS News Blog
Scott Helme
Scott Helme
爱范儿
爱范儿
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
腾讯CDC
I
Intezer
J
Java Code Geeks
大猫的无限游戏
大猫的无限游戏
Microsoft Security Blog
Microsoft Security Blog
人人都是产品经理
人人都是产品经理
G
GRAHAM CLULEY
N
News | PayPal Newsroom
博客园 - 三生石上(FineUI控件)
A
Arctic Wolf
F
Fortinet All Blogs
The Register - Security
The Register - Security
Recent Commits to openclaw:main
Recent Commits to openclaw:main
博客园 - 【当耐特】

博客园 - taowen

DDD Example clearing & settlement Local Optimization Revisited 集群管理要点 We are doomed, and RPC does not help 我想要的智能电视一键播放体验 Veil框架设计理念 【北京】创业公司诚邀主力Python工程师(技术合伙人) Word 与 Excel 同步 我的GIT工作流程 多维数据查询效率分析(3) 多维数据查询效率分析(2) 多维数据查询效率分析(1) 高性能计算摘要 为什么我的敏捷项目有如此多的问题? 提高程序员的准入门槛? 持续部署才是王道 企业定制软件开发的两个核心问题 组织模式 - Introduction
Java 7 实现代码的即改即用
taowen · 2012-03-11 · via 博客园 - taowen
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;

import static java.nio.file.StandardWatchEventKinds.*;

public class WatchDog implements Launcher {

private static Logger LOGGER = LoggerFactory.getLogger(WatchDog.class);
public static final String ENV_KEY_TARGET = "WATCH_DOG_TARGET";
private final Launcher launcher;

public WatchDog(Launcher launcher) {
this.launcher = launcher;
}

@Override
public void launch(String[] args) {
if (!startWatchDog()) {
launcher.launch(args);
}
}

private static boolean startWatchDog() {
String target = System.getenv(ENV_KEY_TARGET);
if (null == target) {
LOGGER.debug("Do not have target for watch dog, launch directly");
return false;
}
LOGGER.debug("Watch dog is watching " + target + " ...");
watch(target);
return true;
}

private static void watch(String target) {
try {
int thisProcessId = Integer.valueOf(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
String thisProcessCommand = getProcessCommand(thisProcessId);
Process subProcess = launchWithoutWatchDog(thisProcessCommand);
final WatchService watchService = FileSystems.getDefault().newWatchService();
try {
Path targetPath = Paths.get(target);
Files.walkFileTree(targetPath, new SimpleFileVisitor<Path>(){
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
dir.register(watchService, ENTRY_MODIFY, ENTRY_DELETE, ENTRY_CREATE);
return super.preVisitDirectory(dir, attrs);
}
});
while (true) {
WatchKey key = watchService.take();
key.pollEvents();
key.reset();
while (null != (key = watchService.poll())) {
key.pollEvents();
key.reset();
}
subProcess.destroy();
subProcess = launchWithoutWatchDog(thisProcessCommand);
}
} finally {
watchService.close();
}
} catch (Throwable e) {
throw new RuntimeException("Failed to watch " + target, e);
}
}

private static String getProcessCommand(int processId) {
String command = "pargs -l " + processId;
try {
Process process = Runtime.getRuntime().exec(command);
process.waitFor();
return readAll(process.getInputStream());
} catch (Throwable e) {
throw new RuntimeException("Failed to execute " + command, e);
}
}

private static String readAll(InputStream inputStream) throws IOException {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder result = new StringBuilder();
String line;
while (null != (line = reader.readLine())) {
result.append(line);
}
return result.toString();
} finally {
inputStream.close();
}
}

private static Process launchWithoutWatchDog(String command) {
try {
LOGGER.info("Launch: " + command);
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command(command.replace("'", "").split(" "));
processBuilder.environment().remove(ENV_KEY_TARGET);
processBuilder.inheritIO();
return processBuilder.start();
} catch (Throwable e) {
throw new RuntimeException("Failed to launch without watch dog: " + command, e);
}
}
}

public interface Launcher {

public void launch(String[] args);
}


五项关键技术:

  1. 代码改动的时候自动更新class,这个部分交由IDE来完成。
  2. 获取当前Java进程的启动命令行
    1. 获取当前进程的PID,由JMX的api完成
    2. 由PID获得命令行参数,这个部分由solaris的pargs完成,其他操作系统也有类似命令
  3. 探测文件夹内容的改动,由Java7的WatchServer完成
  4. 在Java进程内,启动另外一个Java进程。由Java7的ProcessBuilder完成。注意inheritIO这个太方便了。
  5. 同一个main函数,两种执行状态(监控和非监控)。由传入不同的环境变量完成。如果没有WATCH_DOG_TARGET那么就执行真正的main,如果有则把当前进程作为监控进程。