public static FileLock obtainLock(Path dirPath, String lockName) throws IOException {
        if (!Files.isDirectory(dirPath)) {
            Files.createDirectories(dirPath);
        }
        Path lockPath = dirPath.resolve(lockName);

        try {
            Files.createFile(lockPath);
        } catch (IOException ignore) {
            // we must create the file to have a truly canonical path.
            // if it's already created, we don't care. if it can't be created, it will fail below.
        }

        // fails if the lock file does not exist
        final Path realLockPath = lockPath.toRealPath();

        if (!LOCK_HELD.add(realLockPath.toString())) {
            throw new LockException("Lock held by this virtual machine on lock path: " + realLockPath);
        }
        FileChannel channel = null;
        FileLock lock;
        try {
            channel = FileChannel.open(realLockPath, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
            lock = channel.tryLock();
            if (lock == null) {
                throw new LockException("Lock held by another program on lock path: " + realLockPath);
            }
        } catch (IOException ex) {
            try {
                if (channel != null) {
                    channel.close();
                }
            } catch (Throwable t) {
                // suppress any channel close exceptions
            }

            boolean removed = LOCK_HELD.remove(realLockPath.toString());
            if (!removed) {
                throw new LockException("Lock path was cleared but never marked as held: " + realLockPath, ex);
            }

            throw ex;
        }

        LOCK_MAP.put(lock, realLockPath.toString());
        return lock;
    }
@Test
    public void crossJvmObtainLockOnLocked() throws Exception {
        Process p = null;
        String lockFile = ".testCrossJvm";
        FileLock lock = null;

        // Build the command to spawn a children JVM.
        String[] cmd = {
            Paths.get(System.getProperty("java.home"), "bin", "java").toString(),
            "-cp", System.getProperty("java.class.path"),
            Class.forName("org.logstash.FileLockFactoryMain").getName(),
            lockDir.toString(), lockFile
        };

        try {
            // Start the children program that will lock the file.
            p = new ProcessBuilder(cmd).start();
            InputStream is = p.getInputStream();
            /* Wait the children program write to stdout, meaning the file
             * is locked. Set a timeout to ensure it returns.
             */
            Future<Integer> future = executor.submit(() -> {return is.read();});
            assertTrue(future.get(30, TimeUnit.SECONDS) > -1);

            // Check the children process is still running.
            assertThat(p.isAlive(), is(equalTo(true)));

            try {
                // Try to obtain the lock held by the children process.
                FileLockFactory.obtainLock(lockDir, lockFile);
                fail("Should have threw an exception");
            } catch (LockException e) {
                // Expected exception as the file is already locked.
            }
        } finally {
            if (p != null) {
                p.destroy();
            }
        }
    }