Я использую блокировку файлов как средство предотвращения нескольких запусков моего приложения:
FileLock lock = fc.tryLock();
if (lock == null) {
System.out.println("Error: The process is already running.");
}
Пока все хорошо. Теперь я хотел бы написать еще один процесс, который сможет убить первый. Я хотел бы записать текущий PID в файл блокировки. Второй процесс подтвердит, что блокировка здесь (то есть процесс запущен), прочитает файл и уничтожит PID. Проверка блокировки перед чтением является обязательной, поскольку ОС может перезапускать PID: основной процесс может быть остановлен, а его PID повторно использован другим процессом. Проблема с чтением файла невозможна из-за блокировки (хотя я думал, что блокировка только помешает записи ...)
Вот упрощенный код:
public class TestLock {
public static void main(String[] args) throws Exception {
if (args.length == 1 && "kill".equals(args[0])) {
kill();
} else {
run();
}
}
private static void run() throws Exception {
File file = new File("test.lock");
try (FileOutputStream fos = new FileOutputStream(file)) {
FileLock lock = fos.getChannel().tryLock();
if (lock == null) {
System.err.println("Error: The process is already running.");
} else {
int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
System.out.println("Process is launched with PID = " + pid);
fos.write(String.valueOf(pid).getBytes("UTF-8"));
while(true) {
Thread.sleep(3000);
System.out.println("App is running");
}
}
}
}
private static void kill() throws Exception {
File file = new File("test.lock");
if (!file.exists()) {
System.err.println("Error: The process is not running.");
return;
}
try (FileChannel fc = FileChannel.open(file.toPath(), StandardOpenOption.READ)) {
FileLock lock = fc.tryLock(0L, Long.MAX_VALUE, true);
if (lock == null) {
ByteBuffer bb = ByteBuffer.allocate(20);
fc.read(bb);
String pid = new String(bb.array(), "UTF-8").trim();
System.out.println(pid);
// Kill the process
} else {
System.err.println("Error: The process is not running.");
}
}
}
}
Если я запускаю приложение дважды без аргумента второй экземпляр отображает «Ошибка: процесс уже запущен». Если я пытаюсь завершить процесс, пока он не запущен, появляется сообщение «Ошибка: процесс не запущен». Но если я пытаюсь завершить работающий процесс, я получаю IOException «Процесс не может получить доступ к файлу, потому что другой процесс заблокировал часть файла»
Просмотр в других потоках, что блокировки будут только рекомендательными (не действительно блокировка, если не проверено, если я правильно понял), я попытался снять проверку блокировки и использовать простой FileReader в методе kill, но я получаю ту же ошибку. (и в любом случае, я бы предпочел этого не делать из-за повторного использования PID, как указано ранее)