zoukankan      html  css  js  c++  java
  • Java 7 实现代码的即改即用

    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,如果有则把当前进程作为监控进程。
  • 相关阅读:
    MySQL--mysqldump的权限说明
    JS--switch 语句
    psutil官方文档
    mysql 性能分析套件
    mysql 在启动时配置文件的查找方式
    mysql中的意向锁IS,IX
    mysql innodb_double_write特性
    mysql sql_mode 之 NO_ENGINE_SUBSTITUTION
    编译安装hph
    pip list 和 pip freeze
  • 原文地址:https://www.cnblogs.com/taowen/p/2389742.html
Copyright © 2011-2022 走看看