Configuring a lock file read in Java

I would like to configure a lock file read in Java. That is, the file has such that when wrapping using FileInputStream and any read() method, call blocks are called.

I can’t come up with a simple OS-independent way - on Unix-like operating systems, I could try to create FIFO using mkfifo and read from this file. A possible job would be to simply create a very large file and read from it - the reading is unlikely to complete before I catch the stack, but it is ugly and slow (and indeed reading can be incredibly fast when cached).

The corresponding read() socket is trivial to configure β€” create the socket yourself and read it, and you can have a deterministic lock.

The goal is to check the method stack to determine which top frames are in that case. Imagine that I have a component that periodically displays stack traces of all running threads and then tries to classify what this thread is doing at the moment. One thing he can do is an IO file. So I need to know what the "top of the stack" looks like when I enter the file. I have already determined that through experimentation (just read the file in different ways and try the stack), but I want to write a test that will fail if it ever changes.

A natural way to write such a test is to start a stream that reads a file and then examine the top frame (s). To do this reliably, I want to block reading (otherwise the thread may finish reading before the stack trace is executed, etc.).

+7
java io testing mkfifo
source share
6 answers

To get guaranteed locked I / O, read from the console, for example. /dev/console on Linux or CON on Windows.

To make this platform independent, you can hack FileDescriptor from FileInputStream :

  // Open a dummy FileInputStream File f = File.createTempFile("dummy", ".tmp"); f.deleteOnExit(); FileInputStream fis = new FileInputStream(f); // Replace FileInputStream descriptor with stdin Field fd = FileInputStream.class.getDeclaredField("fd"); fd.setAccessible(true); fd.set(fis, FileDescriptor.in); System.out.println("Reading..."); fis.read(); System.out.println("Complete"); 

UPDATE

I realized that you don’t even need a locking method. In order to get the correct stack, you can call read() on an invalid file stream:

  FileInputStream fis = new FileInputStream(new FileDescriptor()); fis.read(); // This will throw IOException exactly with the right stacktrace 

If you still need read() lock, named pipes are the way to go: run mkfifo using Runtime.exec on POSIX systems or create \\.\PIPE\MyPipeName on Windows.

+5
source share

I generally do not know how to make a file offline, which will always be blocked when reading.

If I tried to find the stack trace when a certain function was called, I would run the program under the debugger and set a breakpoint for this function. Although the control points of the method slow down your program and give you different results than usual if time is important.

If you have access to the source code of the program, you can create a fake FileInputStream that extends the real one, but always blocks reading. All you have to do is disable import instructions throughout the code. However, this will not lead to a capture of places where you cannot turn off import instructions, and it can be painful if there is a lot of code.

If you want to use your own FileInputStream without changing the source code of the program or compilation, you can create a custom class loader that loads your own FileInputStream class instead of the real one. You can specify which class loader to use on the command line:

 java -Djava.system.class.loader=com.test.MyClassLoader xxx 

Now, when I think about it, I have an even better idea, instead of creating a custom FileInputStream that blocks read (), create your own FileInputStream that displays stack traces on read (). The custom class can then call the real version of read (). This way you get all the stack traces for all calls.

+1
source share

From my understanding, you want to write a test that checks the stack trace of the FileInputStream.read() method. What about descendants of FileInputStream if they override the read() method?

If you do not need to check the descendants, I think you can use the JVM Tool Interface by inserting a breakpoint at runtime the desired method and in the case of processing this event (breakpoint) - reset the stack trace. After the dump completes, you remove the breakpoint and continue execution. (All this happens at runtime using this API, without black magic :))

+1
source share

You can have a separate stream for viewing changes in the file access time and dumping the jvm stream when this happens. Regarding the generation of a stream dump in the code, I have not tried it, but it looks like it answered here: Generate a Java stream dump without rebooting.

I don't know how well this will work with synchronization between your threads, but I think it should be pretty close. I am also not 100% of the OS independence of this solution, since I have not tested it, but it should work for most modern systems. See Javadocs on java.nio.file.attribute.BasicFileAttributes to see what will return if it is not supported.

0
source share

One trick: if you can change your API to return a Reader instead of a File , then you can wrap a String using StringReader ( class SlowAsRubyStringReader extends Reader ), which overrides the various int read() methods with Thread.sleep(500) before it will do the real work. Of course, only during testing.

@see http://docs.oracle.com/javase/7/docs/api/java/io/StringReader.html

I think there is a big problem here, not just files: you want to check the context in which the API is called during test cases, right? That is, you want to examine the stack and say: "Yeah! I caught that you are calling the MudFactory API from the JustTookABath object, OUTRAGEOUS!". If so, then you may have to delve into dynamic proxies, which allows you to capture function calls or use aspect-oriented programming, which allows you to do the same, but in a more systematic way. See http://en.wikipedia.org/wiki/Pointcut

0
source share

read() quickly grows into native code, so yes, you probably need to switch to locking at this level. Alternatively, you might consider registering a stack trace at a point in your code before or after read() .

Something like:

 log ( ExceptionUtils.getStackTrace(new Exception()) ); 

ExceptionUtils doco is here: https://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/exception/ExceptionUtils.html

-one
source share

All Articles