While running debugger, the program pauses on initializing object streams from server main input output streams. Following is the code :
public TFileReader(Client cli)throws Exception{
this.cli = cli;
fileSock = new Socket(cli.ServerIp(), cli.FilePort());
fobjIn = new ObjectInputStream(fileSock.getInputStream());
fobjOut = new ObjectOutputStream(fileSock.getOutputStream());
fobjOut.flush();
}
#Override
public void run(){
try{
System.out.println("file reader thread online");
fobjOut.writeObject(cli.Name());
fobjOut.flush();
String per = (String) fobjIn.readObject();
System.out.println(per+"video filing...");
if(!per.equals("OKF"))
{
throw new Exception("Error In retriving video.");
}
It pauses on fobjIn and do not go to execute fobjOut although fobjIn it passes from fobjIn breakpoint but do not hit out breakpoint.
I would keep it simple like this
public TFileReader(Client cli) throws IOException {
this.cli = cli;
socket = new Socket(cli.ServerIp(), cli.FilePort());
out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
in = new ObjectInputStream(socket.getInputStream());
}
public void writeObject(Object o) throw IOException {
out.writeObject(o);
out.reset();
out.flush();
}
public <T> T readObject() throw IOException {
return (T) in.readObject();
}
public void close() throws IOException {
in.close();
out.close();
socket.close();
}
The problem is that ObjectInputStream pre-reads data on initialization.
The preferred solution is at Java Creating a new ObjectInputStream Blocks: always initialize your ObjectOutputStream before initializing your ObjectInputStream, so that the "handshake" that the two use internally can be initiated.
When you don't control all the code and cannot change the order, consider delaying the OIS initialization until data is available (InputStream.available or mark/read/reset on a buffered stream wrapping it, etc).
Related
I have a method that writes data from a list to a file, a method that reads data from a file into a list and a method that writes data from a list in a file to the specified number of times. I'm trying to extract data from a file after I use the first method writeFile () everything works fine. I read the data from the file into the list by readFile () method. After that I use my method which writes to the file the number of times I need, everything is fine, it writes multyWrite (). But after that I can not read the data from the file in the readFile () method since I get `
Exception stack trace:
Exception in thread "main" java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1599)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
at ProductService.readFile(ProductService.java:47)
at Main.main(Main.java:21)
I know that I should use objectOutputStream.reset (), but where would it be better to use it?
private String fileName;
private ProductInterface<FlyingMachine> productService = new ProductInterfaceImpl();
private ObjectOutputStream objectOutputStream;
private FileOutputStream fileOutputStream;
public ProductService(String fileName) throws IOException {
this.fileName = fileName;
fileOutputStream = new FileOutputStream(fileName);
this.objectOutputStream = new ObjectOutputStream(fileOutputStream);
}
public void writeFile() throws IOException {
try {
for (FlyingMachine f : productService.getProductContainer()) {
objectOutputStream.writeObject(f);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (objectOutputStream != null) {
objectOutputStream.flush();
objectOutputStream.close();
fileOutputStream.close();
}
}
}`
public void readFile() throws IOException {
ObjectInputStream objectInputStream = null;
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(fileName);
objectInputStream = new ObjectInputStream(fileInputStream);
while (fileInputStream.available() > 0) {
FlyingMachine flyingMachine = (FlyingMachine) objectInputStream.readObject();
productService.getProductContainer().add(flyingMachine);
}
} catch (ClassNotFoundException | EOFException e) {
e.printStackTrace();
} finally {
if (objectInputStream != null) {
objectInputStream.close();
fileInputStream.close();
}
}
}
public void multyWrite(int number) throws IOException {
for (int i = 0; i < number; i++) {
try {
fileOutputStream = new FileOutputStream(fileName, true);
objectOutputStream = new ObjectOutputStream(fileOutputStream);
for (FlyingMachine f : productService.getProductContainer()) {
objectOutputStream.writeObject(f);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (objectOutputStream != null) {
objectOutputStream.flush();
objectOutputStream.close();
}
}
}
}
You create a new ObjectOutputStream in the constructor. In writeFile you use that OOS instance and close it. But in multyWrite you don't use it and instead create new instances.
Now when you call multyWrite without having called writeFile first, that first OOS will still be open, but the OOS you create in multyWrite doesn't know that - thus causing your file to have two OOS headers after another.
And then when you try to read such a file, the ObjectInputStream will find the first header (all is fine) and then unexpectedly find the second header, while it expected a type code. That header starts with 0xAC, hence throwing the exception message "invalid type code: AC".
To fix this, either have multyWrite use the OOS constructed in your constructor, the same way writeFile does, or make sure that that OOS is closed before you create a new one.
It's generally not a good idea to open a stream (of any kind) in a constructor and then rely on external code calling a specific method to close it. Better create streams when you need them and close them directly.
I'm experimenting with Serialization and wrote the following class:
public static void main(String[] args) throws ClassNotFoundException{
File file = new File("D:/serializable.txt");
try(FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream ous = new ObjectOutputStream(fos);
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis)){
// SerialTest st = new SerialTest();
// ous.writeObject(st);
SerialTest st = (SerialTest) ois.readObject();
System.out.println(st);
} catch (IOException e) {
e.printStackTrace();
}
}
Serialized class:
public static class SerialTest implements Serializable{
private int count;
private Object object;
public int count(){
return count;
}
public Object object(){
return object;
}
private void readObject(ObjectOutputStream ous) throws IOException{
ous.writeObject(object);
ous.writeInt(count);
}
private void writeObject(ObjectInputStream ois) throws IOException, ClassNotFoundException{
ois.readInt();
ois.readObject();
}
}
After serializing the object as in the commeted code, I tried to desirialize it as specified here. I got
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2598)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1318)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
Moroever, the content of the file containing the serialized object is chaged.
But when I remove the resource-declarations
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream ous = new ObjectOutputStream(fos);
from the try-with-resources clasuse it works completely fine. Why? Why the resource declarations affects the deserialization?
Well without the write calls, you're currently creating an empty file to start with, because that's what the FileOutputStream constructor you're calling does. If the file already exists, it is truncated to be 0 bytes long. So when you then try to read an object from it, there's nothing to read.
Even with the writing part uncommented, there's still the possibility of buffering issues, where the data hasn't actually been written to the file yet.
I would strongly urge you to write the file and close the output stream, and then separately open it for input. Having the same file open for read and write at the same time seems like a recipe for confusing results to me.
So the code would look something like this:
// Exception handling omitted as this is just test code
public static void main(String[] args) throws Exception {
File file = new File("D:/serializable.txt");
try (FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream ous = new ObjectOutputStream(fos)) {
SerialTest st = new SerialTest();
ous.writeObject(st);
}
try (FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis)) {
SerialTest st = (SerialTest) ois.readObject();
System.out.println(st);
}
}
Leaving aside the fact that you obviously have the content of readObject() and writeObject() back to front:
private void readObject(ObjectOutputStream ous) throws IOException{
ous.writeObject(object);
ous.writeInt(count);
}
Here you are writing first the object then the integer.
private void writeObject(ObjectInputStream ois) throws IOException, ClassNotFoundException{
ois.readInt();
ois.readObject();
}
Here you are reading first the integer then the object.
Ain't gonna work.
BUT ... You don't need either of these methods. Remove them. Or, if you want to serialize data of the parent class, fix them to (a) call defaultReadObject() and defaultWriteObject() respectively, and get rid of what you already have in there, which will already happen by default, or at least when you read the object and the integer in the same order as you wrote them, store them into the respective instance members.
NB serialized data isn't text and shouldn't be stored in files named .txt.
I have a data producer that runs in a separate thread and pushes generated data into PipedOutputStream which is connected to PipedInputStream. A reference of this input stream is exposed via public API so that any client can use it. The PipedInputStream contains a limited buffer which, if full, blocks the data producer. Basically, as the client reads data from the input stream, new data is generated by the data producer.
The problem is that the data producer may fail and throw an exception. But as the consumer is running in a separate thread, there is no nice way to get the exception to the client.
What I do is that I catch that exception and close the input stream. That will result in a IOException with message "Pipe closed" on the client side but I would really like to give the client the real reason behind that.
This is a rough code of my API:
public InputStream getData() {
final PipedInputStream inputStream = new PipedInputStream(config.getPipeBufferSize());
final PipedOutputStream outputStream = new PipedOutputStream(inputStream);
Thread thread = new Thread(() -> {
try {
// Start producing the data and push it into output stream.
// The production my fail and throw an Exception with the reason
} catch (Exception e) {
try {
// What to do here?
outputStream.close();
inputStream.close();
} catch (IOException e1) {
}
}
});
thread.start();
return inputStream;
}
I have two ideas how to fix that:
Store the exception in the parent object and expose it to the client via API. I. e. if the reading fails with an IOException, the client could ask the API for the reason.
Extend / re-implement the piped streams so that I could pass a reason to the close() method. Then the IOException thrown by the stream could contain that reason as a message.
Any better ideas?
Coincidentally I just wrote similar code to allow GZip compression of a stream. You don't need to extend PipedInputStream, just FilterInputStream will do and return a wrapped version, e.g.
final PipedInputStream in = new PipedInputStream();
final InputStreamWithFinalExceptionCheck inWithException = new InputStreamWithFinalExceptionCheck(in);
final PipedOutputStream out = new PipedOutputStream(in);
Thread thread = new Thread(() -> {
try {
// Start producing the data and push it into output stream.
// The production my fail and throw an Exception with the reason
} catch (final IOException e) {
inWithException.fail(e);
} finally {
inWithException.countDown();
}
});
thread.start();
return inWithException;
And then InputStreamWithFinalExceptionCheck is just
private static final class InputStreamWithFinalExceptionCheck extends FilterInputStream {
private final AtomicReference<IOException> exception = new AtomicReference<>(null);
private final CountDownLatch complete = new CountDownLatch(1);
public InputStreamWithFinalExceptionCheck(final InputStream stream) {
super(stream);
}
#Override
public void close() throws IOException {
try {
complete.await();
final IOException e = exception.get();
if (e != null) {
throw e;
}
} catch (final InterruptedException e) {
throw new IOException("Interrupted while waiting for synchronised closure");
} finally {
stream.close();
}
}
public void fail(final IOException e) {
exception.set(Preconditions.checkNotNull(e));
}
public void countDown() {complete.countDown();}
}
This is my implementation, taken from above accepted answer https://stackoverflow.com/a/33698661/5165540 , where I don't use the CountDownLatch complete.await() as it would cause a deadlock if the InputStream gets abruptly closed before the writer has finished writing the full content.
I still set the exception caught when PipedOutpuStream is being used, and I create the PipedOutputStream in the spawn thread, using a try-finally-resource pattern to ensure it gets closed, waiting in the Supplier until the 2 streams are piped.
Supplier<InputStream> streamSupplier = new Supplier<InputStream>() {
#Override
public InputStream get() {
final AtomicReference<IOException> osException = new AtomicReference<>();
final CountDownLatch piped = new CountDownLatch(1);
final PipedInputStream is = new PipedInputStream();
FilterInputStream fis = new FilterInputStream(is) {
#Override
public void close() throws IOException {
try {
IOException e = osException.get();
if (e != null) {
//Exception thrown by the write will bubble up to InputStream reader
throw new IOException("IOException in writer", e);
}
} finally {
super.close();
}
};
};
Thread t = new Thread(() -> {
try (PipedOutputStream os = new PipedOutputStream(is)) {
piped.countDown();
writeIozToStream(os, projectFile, dataFolder);
} catch (final IOException e) {
osException.set(e);
}
});
t.start();
try {
piped.await();
} catch (InterruptedException e) {
t.cancel();
Thread.currentThread().interrupt();
}
return fis;
}
};
Calling code is something like
try (InputStream is = streamSupplier.getInputStream()) {
//Read stream in full
}
So when is InputStream is closed this will be signaled in the PipedOutputStream causing eventually a "Pipe closed" IOException, ignored at that point.
If I keep instead the complete.await() line in the FilterInputStreamclose() I could suffer from deadlock (PipedInputStream trying to close, waiting on complete.await(), while PipedOutputStream is waiting forever on PipedInputStreamawaitSpace )
I'm writing a program that writes to a single file from both different threads on the same JVM and from different JVM's/processes. Is there a way to lock a file for both threads and processes, so that no matter how many threads/processes are trying to write at the same time, only 1 can write at a time?
Currently I have something similar to the following which works for locking threads, but not for blocking processes. If I try using FileLock on top of the implementation below it appears the synchronized stops working.
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import scripts.com.adz.commons.utils.FileUtilities;
import java.io.*;
public class Foo {
public static void main(String[] args) throws IOException {
Bar bar = new Bar();
bar.start();
while (true) {
FileUtilities.writeObjectToFile("C:\\test.html", "foo");
}
}
}
class Bar extends Thread {
#Override
public void run() {
while (true) {
try {
FileUtilities.writeObjectToFile("C:\\test.html", "bar");
} catch (IOException ignored) {}
}
}
}
class FileUtilitiess {
private static final Object _lock = new Object();
public static <T> T readObjectFromFile(File file) throws IOException, ClassNotFoundException {
synchronized (_lock) {
final byte[] bytes = FileUtils.readFileToByteArray(file);
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(bis = new ByteArrayInputStream(bytes));
return (T) ois.readObject();
} finally {
IOUtils.closeQuietly(ois);
IOUtils.closeQuietly(bis);
}
}
}
public static void writeObjectToFile(File file, Object object) throws IOException {
System.out.println("Sent object: " + object.toString());
synchronized (_lock) {
System.out.println("Writing object: " + object.toString());
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(bos = new ByteArrayOutputStream());
oos.writeObject(object);
FileUtils.writeByteArrayToFile(file, bos.toByteArray());
// - Start: For testing lock.
try {
Thread.sleep(10000);
} catch (InterruptedException ignored) {}
// - End: For testing lock.
} finally {
IOUtils.closeQuietly(oos);
IOUtils.closeQuietly(bos);
}
}
}
}
See FileLock javadoc:
File locks are held on behalf of the entire Java virtual machine.
That means that on the OS level different threads of your application will have the same right to access the locked region.
To lock the file access from different threads you have to encapsulate your file IO code and to enforce synchronized execution.
I have a simple Server-Client socket connection. I encapsulate all my data in objects which are sent backward and forward between the sockets, sent through ObjectStreams.
I have created a "HeartBeat" monitor, which runs in a separate thread, where both the server and the client, every 500ms, send a HeartBeat (empty object) backward and forward to check for connectivity, which works great. However, because of this, when I want to send other data between the server and client, it is mixed up with these HeartBeat objects.
For example my Server is expecting a Login object, but instead gets an object of instance HeartBeat.
My code is a simple client/server setup, so I don't think it'd be necessary to post their code, however, the HeartBeat code is as follows:
private static final int HEARTBEAT_INTERVAL = 500;
private void addHeartBeatMonitor(final Socket socket) {
this.heartBeatTimer = new Timer();
this.heartBeatTimer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
try {
ObjectOutputStream os = new ObjectOutputStream(socket.getOutputStream());
os.writeObject(new HeartBeat());
ObjectInputStream is = new ObjectInputStream(socket.getInputStream());
if (!(is.readObject() instanceof HeartBeat)) { throw new IOException(); }
} catch (IOException e) {
LOG.info("Received disconnect from " + getClientSocket().getInetAddress());
heartBeatTimer.cancel();
if (clientSocket != null) {
try {
clientSocket.close();
} catch (IOException e1) {}
}
} catch (ClassNotFoundException e) {}
}
}, 0, HEARTBEAT_INTERVAL);
}
My options seem to be to as follows:
Ditch the HeartBeat functionality, although there seems to be no other reliable way to check the connection status.
Find some other kind of Socket implementation which will magically fix all of this for me.
Have a synchronized method which oversees all reads and writes to the socket, which discards HeartBeats and sends other objects where they're meant to be.
Some kind of synchronization magic.
Thanks in advance for any help!
EDIT:
Code which reads the Login object (server side):
User result = null;
try {
ObjectInputStream is = new ObjectInputStream(this.getInputStream());
Login request = (Login) is.readObject(); ### ERROR ###
result = this.mongoService.login(request);
ObjectOutputStream os = new ObjectOutputStream(this.getOutputStream());
os.writeObject(result);
} catch (IOException e) {
} catch (ClassNotFoundException e) {}
return result;
Exception as follows:
Exception in thread "Thread-0" java.lang.ClassCastException: model.HeartBeat cannot be cast to model.Login
at socket.SocketServerWorker.login(SocketServerWorker.java:78)
at socket.SocketServerWorker.<init>(SocketServerWorker.java:47)
at socket.SocketServer$2.run(SocketServer.java:50)
at java.lang.Thread.run(Thread.java:744)
Consider doing something like this. I just threw this together, so it's obviously untested, but I'm sure you'll get the idea:
public class HeartBeatMonitor
{
final Map<Class,Consumer> handlers = new HashMap<> ();
final Socket sock;
final ObjectInputStream is;
final ObjectOutputStream os;
public HeartBeatMonitor (final Socket sock)
{
try
{
this.sock = sock;
this.is = new ObjectInputStream (sock.getInputStream ());
this.os = new ObjectOutputStream (sock.getOutputStream ());
}
catch (final IOException e)
{
throw new RuntimeException (e);
}
}
public <T> void setHandler (final Class<T> type, final Consumer<? super T> handler)
{
this.handlers.put (type, handler);
}
// This would be called in a loop
void accept () throws ClassNotFoundException, IOException
{
final Object o = this.is.readObject ();
final Consumer handler = this.handlers.get (o.getClass ());
if (handler != null)
handler.accept (o);
// Else default handler?
}
}