File locking example
This commit is contained in:
parent
65ee6e2207
commit
af27178965
@ -11,5 +11,5 @@ This module contains articles about core Java input and output (IO)
|
||||
- [List Files in a Directory in Java](https://www.baeldung.com/java-list-directory-files)
|
||||
- [Java – Append Data to a File](https://www.baeldung.com/java-append-to-file)
|
||||
- [How to Copy a File with Java](https://www.baeldung.com/java-copy-file)
|
||||
- [Create a Directory in Java](https://www.baeldung.com/java-create-directory)
|
||||
- [Create a Directory in Java](https://www.baeldung.com/java-create-directory)
|
||||
- [[<-- Prev]](/core-java-modules/core-java-io)
|
||||
|
@ -14,5 +14,22 @@
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-java</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<!-- https://mvnrepository.com/artifact/com.github.jnr/jnr-ffi -->
|
||||
<dependency>
|
||||
<groupId>com.github.jnr</groupId>
|
||||
<artifactId>jnr-ffi</artifactId>
|
||||
<version>2.1.11</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.github.jnr/jnr-constants -->
|
||||
<dependency>
|
||||
<groupId>com.github.jnr</groupId>
|
||||
<artifactId>jnr-constants</artifactId>
|
||||
<version>0.9.14</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,105 @@
|
||||
package com.baeldung.lock;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.FileLock;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import jnr.ffi.LibraryLoader;
|
||||
import jnr.ffi.Memory;
|
||||
import jnr.ffi.Pointer;
|
||||
import jnr.ffi.types.pid_t;
|
||||
|
||||
public class FileLocks {
|
||||
|
||||
public static interface LibC {
|
||||
|
||||
public static final int O_NONBLOCK = jnr.constants.platform.OpenFlags.O_NONBLOCK.intValue();
|
||||
public static final int O_RDWR = jnr.constants.platform.OpenFlags.O_RDWR.intValue();
|
||||
public static final int O_EXLOCK = jnr.constants.platform.OpenFlags.O_EXLOCK.intValue();
|
||||
|
||||
public long write(int fd, Pointer data, long len);
|
||||
|
||||
@pid_t
|
||||
long getpid();
|
||||
|
||||
int open(String filename, int flags);
|
||||
|
||||
int close(int fd);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException, InterruptedException {
|
||||
|
||||
Path path = Paths.get("/tmp/foo");
|
||||
|
||||
// Delete the file if it exists
|
||||
Files.deleteIfExists(path);
|
||||
|
||||
// Start with a fresh empty file
|
||||
Files.createFile(path);
|
||||
|
||||
// Prepare some external libc calls. Will only work on systems that have libc.
|
||||
LibC libc = LibraryLoader.create(LibC.class).load("c");
|
||||
byte[] bytes = "Hello from C\n".getBytes("UTF-8");
|
||||
jnr.ffi.Runtime runtime = jnr.ffi.Runtime.getRuntime(libc);
|
||||
Pointer buffer = Memory.allocateDirect(runtime, bytes.length);
|
||||
buffer.put(0, bytes, 0, bytes.length);
|
||||
|
||||
// Open the file through a libc call. This returns a file descriptor.
|
||||
int fd = libc.open(path.toString(), libc.O_RDWR + libc.O_EXLOCK + libc.O_NONBLOCK);
|
||||
System.out.println("Opened the file through a libc call that locks it.");
|
||||
|
||||
// Our java method will see the lock. Itd will be well behaved and won't write to the file.
|
||||
// Note that external processes on POSIX systems would still be able to write to this file ignoring any locks.
|
||||
writeToRandomAccessFile(path, "I won't write this", 0L);
|
||||
|
||||
// Libc opened the file, it can write to its corresponding file handle.
|
||||
libc.write(fd, buffer, bytes.length);
|
||||
|
||||
// Now let's close the file through a libc call, to release its lock.
|
||||
libc.close(fd);
|
||||
System.out.println("Invoked libc's close() method");
|
||||
|
||||
// This time our method won't see the lock and will write to the file.
|
||||
writeToRandomAccessFile(path, "Hello from java", bytes.length);
|
||||
|
||||
System.out.println("Now that all the locks are gone, here are the file contents:");
|
||||
System.out.println("------------------------------------------------------------");
|
||||
Files.lines(path).forEach(System.out::println);
|
||||
|
||||
}
|
||||
|
||||
public static RandomAccessFile writeToRandomAccessFile(Path path, String data, long position) {
|
||||
RandomAccessFile file = null;
|
||||
try {
|
||||
file = new RandomAccessFile(path.toFile(), "rws");
|
||||
FileChannel channel = file.getChannel();
|
||||
// Try to acquire a lock
|
||||
try (FileLock lock = channel.tryLock()) {
|
||||
if (lock == null) {
|
||||
System.out.println("Tried to lock through the FileChannel's lock() method. This file is already locked! It's my responsibility to not write to it, even if the OS would let me!");
|
||||
} else {
|
||||
System.out.println("I don't see a lock on this file anymore. Now I can write to it.");
|
||||
int i = 0;
|
||||
channel.write(
|
||||
ByteBuffer.wrap((data).getBytes(StandardCharsets.UTF_8)), position);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error while locking");
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Other Error.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* Header for class com_baeldung_lock_FileLocks */
|
||||
|
||||
#ifndef _Included_com_baeldung_lock_FileLocks
|
||||
#define _Included_com_baeldung_lock_FileLocks
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
* Class: com_baeldung_lock_FileLocks
|
||||
* Method: getpid
|
||||
* Signature: ()J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_com_baeldung_lock_FileLocks_getpid
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user