Why is this code contains undefined behavior (the program is completed in half the time). How do I make a clean shutdown of the reader when I need to complete the program?
public class Main implements Runnable {
private static BufferedReader reader;
public static void main(String[] args) {
reader = new BufferedReader(new InputStreamReader(System.in));
new Thread(new Main()).start();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
//System.in.close(); // <-- undefined behavior
reader.close(); // <-- undefined behavior
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
try {
reader.readLine();
} catch (IOException ignore) {
}
}
}
Related
We have a windows application, which was tested on Windows XP, 7, 8, 8.1. Application consists of 2 parts: Bootstrap and main application. Bootstrap assures updates of the main app, and updates main app at a particular point. But users were able to force stop Boostrap process via the Task Manager (Ctrl+Shift+ESC->processes) by killing a process named javaw. In that case main app would not update and elder version would be launched. To avoid such issue we introduced interface of Bootstrap with main application via Socket. Here are the VM parameters of Bootstrap when it starts:
javaw.exe -Xms75M -Xmx90M -Xincgc -jar bootstrap.jar
There is a class SocketServer in the bootstrap:
public class Provider {
ServerSocket providerSocket;
Socket connection = null;
ObjectOutputStream out;
ObjectInputStream in;
String message;
public Provider() {
}
public void run() {
try{
providerSocket = new ServerSocket(54345);
connection = providerSocket.accept();
out = new ObjectOutputStream(connection.getOutputStream());
out.flush();
in = new ObjectInputStream(connection.getInputStream());
sendMessage("Connection successful");
do {
try {
message = (String)in.readObject();
if (message.equals("bye")) {
sendMessage("bye");
}
} catch(ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
} while (!message.equals("bye"));
} catch(IOException ioe) {
ioe.printStackTrace();
} finally {
try {
in.close();
out.close();
providerSocket.close();
} catch(IOException ioef) {
ioef.printStackTrace();
}
}
}
public void sendMessage(String msg) {
try {
out.writeObject(msg);
out.flush();
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
public void stop() {
if (providerSocket != null && in != null && out != null && !providerSocket.isClosed()) {
try {
in.close();
out.close();
providerSocket.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}
Main app is being started by Bootstrap via ProcessBuilder like so:
public static void communicate(Process process) {
final BufferedReader stdOut = new BufferedReader(new InputStreamReader(process.getInputStream(), Charset.forName("Windows-1251")));
final BufferedReader stdErr = new BufferedReader(new InputStreamReader(process.getErrorStream(), Charset.forName("Windows-1251")));
//InputStream
new Thread() {
#Override
public void run() {
String line;
try {
while ((line = stdOut.readLine()) != null) {
debugOut(line);
}
} catch (Exception e) {
e.printStackTrace();
}
try {
stdOut.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}.start();
//ErrorStream
new Thread() {
#Override
public void run() {
String line;
try {
while ((line = stdErr.readLine()) != null) {
debugOut(line);
}
} catch (Exception e) {
e.printStackTrace();
}
try {
stdErr.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}.start();
try {
final Provider provider = new Provider();
ExecutorService pEexec = Executors.newCachedThreadPool();
Future<Void> FPExec = pEexec.submit(new Callable<Void>() {
#Override
public Void call() throws Exception {
while (!Thread.currentThread().isInterrupted()) {
provider.run();
}
return null;
}
});
pEexec.shutdown();
process.waitFor();
debugOut("[MainApp] Exit");
provider.stop();
FPExec.cancel(true);
debug("Destroy process");
process.destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void startApp() {
try {
ArrayList<String> params = new ArrayList<String>();
...
params.add("-Xms32M");
params.add("-Xmx48M");
params.add("-Xincgc");
params.add("-cp");
params.add(new File(pathToJar, "mainapp.jar").getPath());
params.add("net.craftwork.mainapp.AppStart");
params.add(licCode());
ProcessBuilder procBuild = new ProcessBuilder(params);
debugOut("[MainApp] Start");
Process proc = procBuild.start();
communicate(proc);
} catch (Exception e) {
e.printStackTrace();
}
}
There is a class SocketClient in the main app:
public class Requester {
Socket requestSocket;
ObjectOutputStream out;
ObjectInputStream in;
String message;
static Future<Void> oExec;
Requester() {
}
void run() {
try {
requestSocket = new Socket("localhost", 54345);
out = new ObjectOutputStream(requestSocket.getOutputStream());
out.flush();
in = new ObjectInputStream(requestSocket.getInputStream());
do {
try {
message = (String)in.readObject();
sendMessage("bye");
} catch(ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
} while (!message.equals("bye"));
} catch(UnknownHostException uhe) {
uhe.printStackTrace();
} catch(IOException ioe) {
ioe.printStackTrace();
oExec.cancel(true);
CommonUtils.debug("Bootstrap not found. Exit.");
System.exit(0);
} finally {
try {
in.close();
out.close();
requestSocket.close();
} catch(IOException ioef) {
ioef.printStackTrace();
}
}
}
void sendMessage(String msg) {
try {
out.writeObject(msg);
out.flush();
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
public static void main() {
final Requester client = new Requester();
ExecutorService exec = Executors.newCachedThreadPool();
oExec = exec.submit(new Callable<Void>() {
#Override
public Void call() throws Exception {
while (!Thread.currentThread().isInterrupted()) {
client.run();
Thread.sleep(1000);
}
return null;
}
});
exec.shutdown();
}
}
Socket Client is called when main application starts
public class AppStart {
public static void main(final String[] args) {
Requester.main();
EventQueue.invokeLater(new Runnable() {
public void run() {
...
}
});
}
}
This is all to it I do believe. Whole setup worked perfectly fine, even on slower computers. Problem is that after introduction of Socket interface we had major complaints from some users, reporting crashes. Took us some time to figure out the issue, but here is what we found: computers with Intel processors are perfectly fine, only ones with AMD processors crash. Crash normally happens within 3 to 15 minutes from the start of Bootstrap. When crash occurs resources of the computer are not fully used, processor workload is about 20-50% and RAM is quite free as well. When crash occurs user is only able to reset computer using hardware reset or power button, nothing else responds. All users have latest JAVA 1.7.0_51. Whether system is 32 or 64 bit does both crash (or not crash if it is Intel based). Please share your thoughts. May be someone had identical issues and could help me to figure this out.
I have a a GPS receptor. I create a class to retrieve all the GPS data on my Eclipse Console.
(This is the code of makia42)
public class COM implements Runnable{
static Thread myThread=null;
static BufferedReader br;
static BufferedWriter wr;
static InputStreamReader isr;
static OutputStreamWriter osw;
static java.io.RandomAccessFile port;
public COM(){ /**Constructeur*/
myThread=new Thread(this);
}
public void start(){
try {
port=new java.io.RandomAccessFile("COM3","rwd");
port.writeBytes("\r\n");
port.writeBytes("c,31,0,0,5\r\n");
port.writeBytes("T,1000,1\r\n");
}
catch (Exception e) {
System.out.println("start "+e.toString());
}
myThread.start();
}
public void run() {
System.out.println("lecture COM...");
for(;;){
String st = null;
try {
st=port.readLine();
} catch (IOException e) {System.out.println(e.getMessage());}
System.out.println(st);
}
}
public static void main(String[] args) {
COM temp= new COM();
temp.start();
}
}
I have another class which is a frame containing a button and a JTextArea. This class is in communication with my first class COM.
When i click the button, COM is starting and show me the data in my Eclipse Console.
But now, I'd like to show it on my JTextArea.
How can I do it ?
Best regards,
Tofuw
Take a moment to read about this pattern.
Make the Thread a Subject. Before starting register the instance of the class that contains the JTextArea as the Observer with the instance of the Thread. At the run() instead of printing on the console, use the notify(String);
public void run() {
System.out.println("lecture COM...");
for(;;){
String st = null;
try {
st=port.readLine();
} catch (IOException e) {System.out.println(e.getMessage());}
System.out.println(st);
}
}
Change to
public void run() {
System.out.println("lecture COM...");
for(;;){
String st = null;
try {
st=port.readLine();
} catch (IOException e) {System.out.println(e.getMessage());}
notifyObservers(st); //Pass the data to the observers.
}
}
EDIT:
I suppose you can rewrite the Thread to a simple class. It will render the program unresponsive while it reads, that's why you have a Thread. I suppose you can implement a cleaner way using Future<String>
public class GpsReader {
public class GenericGPSException extends Exception {
public GenericGPSException(String message, Throwable cause) {
super(message, cause);
}
}
public static void main(String[] args) {
// Example of usage
GpsReader gpsReader = new GpsReader();
String messageFromDevice;
try {
// Try read it
messageFromDevice = gpsReader.getCoordinate();
} catch (GenericGPSException e) {
// Error, what does it says?
messageFromDevice = e.getMessage();
}
JTextArea mockArea = new JTextArea();
// Show to user anything that comes to it.
mockArea.setText(messageFromDevice);
}
private boolean isReady;
private RandomAccessFile port;
public GpsReader() {
}
public String getCoordinate() throws GenericGPSException {
if (!isReady) {
try {
port = new RandomAccessFile("COM3", "rwd");
port.writeBytes("\r\n");
port.writeBytes("c,31,0,0,5\r\n");
port.writeBytes("T,1000,1\r\n");
isReady = true;
} catch (FileNotFoundException e) {
throw new GenericGPSException(
"Error at starting communication to Device ", e);
} catch (IOException e) {
throw new GenericGPSException(
"Error at starting communication to Device ", e);
}
}
try {
return port.readLine();
} catch (IOException e) {
throw new GenericGPSException("Error at reading the Device ", e);
}
}
}
Is it true that notify works only after thread is finished? In code below I can't get notification until I comment while (true). How to tell main thread that part of thread job is done?
public class ThreadMain {
public Thread reader;
private class SerialReader implements Runnable {
public void run() {
while (true) {
try {
Thread.sleep(3000);
synchronized(this) {
System.out.println("notifying");
notify();
System.out.println("notifying done");
}
} catch (Exception e) {
System.out.println(e);
}
}
}
}
ThreadMain() {
reader = new Thread(new SerialReader());
}
public static void main(String [] args) {
ThreadMain d= new ThreadMain();
d.reader.start();
synchronized(d.reader) {
try {
d.reader.wait();
System.out.println("got notify");
} catch (Exception e) {
System.out.println(e);
}
}
}
}
You should try to avoid using wait and notify with the newer versions of Java, as they're difficult to get right. Try using something like a BlockingQueue instead
public class ThreadMain {
public final BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
private class SerialReader implements Runnable {
public void run() {
while (true) {
try {
Thread.sleep(3000);
System.out.println("notifying");
queue.offer(Boolean.TRUE);
System.out.println("notifying done");
} catch (Exception e) {
System.out.println(e);
}
}
}
}
ThreadMain() {
reader = new Thread(new SerialReader());
}
public static void main(String [] args) {
ThreadMain d= new ThreadMain();
d.reader.start();
try {
d.queue.take(); // block until something is put in the queue
System.out.println("got notify");
} catch (Exception e) {
System.out.println(e);
}
}
}
If you want to be notified when the Thread t completes, call t.join() in the calling Thread. This will block until t has finished its Runnable.
As user oddparity noted in the comments, you are calling wait() and notify() on different objects. A possible fix for this would be to make your SerialReader extend Thread rather than implement Runnable and then assigning reader to be a new instance of the SerialReader directly. :
public class ThreadMain {
public Thread reader;
private class SerialReader extends Thread {
public void run() {
while (true) {
try {
Thread.sleep(3000);
synchronized(this) {
System.out.println("notifying");
notify();
System.out.println("notifying done");
}
} catch (Exception e) {
System.out.println(e);
}
}
}
}
ThreadMain() {
reader = new SerialReader();
}
public static void main(String [] args) {
ThreadMain d= new ThreadMain();
d.reader.start();
synchronized(d.reader) {
try {
d.reader.wait();
System.out.println("got notify");
} catch (Exception e) {
System.out.println(e);
}
}
}
}
If you want to use Runnable with wait()/notify() you can do it this way :
public class ThreadMain {
public Thread reader;
private class SerialReader implements Runnable {
public void run() {
Thread thisThread = Thread.currentThread();
while (true) {
try {
Thread.sleep(3000);
synchronized (thisThread) {
System.out.println("notifying");
thisThread.notify();
System.out.println("notifying done");
}
} catch (Exception e) {
System.out.println(e);
}
}
}
}
ThreadMain() {
reader = new Thread(new SerialReader());
}
public static void main(String[] args) {
ThreadMain d = new ThreadMain();
d.reader.start();
synchronized (d.reader) {
try {
d.reader.wait();
System.out.println("got notify");
} catch (Exception e) {
System.out.println(e);
}
}
}
}
Here is the code:
public static void main(String[] args) {
SocketWorker worker = null;
MyIOConsole mio = null;
try {
portNumber = 2012;
worker = new SocketWorker();
worker.assignPort(portNumber);
mio = new MyIOConsole();
mio.assignObject(worker);
Thread b = new Thread(mio);
b.start();
worker.run();
} catch (IOException e) {
e.printStackTrace();
}finally{
mio.applicationQuit();
}
}
The SocketWorker is simply a socket, listening the port 2012, and the MyIOConsole, will accept user command,
public class MyConsoleIO implements Runnable {
SocketWorker o;
static BufferedReader reader;
public void assignObject(Object o) {
reader = new BufferedReader(new InputStreamReader(System.in));
this.o = (SocketWorker) o;
}
#Override
public void run() {
String inputString = null;
System.out.println("Press 'q' to kill to program");
try {
inputString = reader.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (inputString.equalsIgnoreCase("q")) {
this.applicationQuit();
}
}
public void applicationQuit(){
this.o.stopWorking();
System.exit(0);
}
}
But when the Socket got the exception, even I catch them, the code
mio.applicationQuit();
keep run. I don't want that, I just want when the user close or crashed the application, the socket will close and quit. How can I solve it?
Add the following. The run method will be called as the JVM is exiting.
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run(){
// cleanup code before JVM exit goes here.
}
});
I need to launch a binary file using Java and then interact with it using input and output streams. I've written a prototype to figure out how it works, but so far the only output I'm getting has been null. When run on its own however the child program produces output. What am I doing wrong?
import java.io.*;
public class Stream {
public static void main(String args[]) {
Process SaddleSumExec = null;
BufferedReader outStream = null;
BufferedReader inStream = null;
try {
SaddleSumExec = Runtime.getRuntime().exec("/home/alex/vendor/program weights.txt list.txt");
}
catch(IOException e) {
System.err.println("Error on inStream.readLine()");
e.printStackTrace();
}
try {
inStream = new BufferedReader(new InputStreamReader
(SaddleSumExec.getInputStream()));
System.out.println(inStream.readLine());
}
catch(IOException e){
System.out.println("Error.");
}
}
}
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
public class Prompt {
//flag to end readers and writer
boolean processEnd = false;
public static void main(String[] args) {
new Prompt();
}
public Prompt() {
Process SaddleSumExec = null;
Input in = new Input(this);
Output out = new Output(this);
Input err = new Input(this);
//thread to read a write console
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
Thread t3 = new Thread(err);
try {
SaddleSumExec = Runtime
.getRuntime()
.exec(
"ConsoleApplication1/bin/Debug/ConsoleApplication1");
in.input = SaddleSumExec.getInputStream();
err.input = SaddleSumExec.getErrorStream();
out.out = SaddleSumExec.getOutputStream();
t2.start();
t1.start();
t3.start();
SaddleSumExec.waitFor();
processEnd = true;
} catch (IOException e) {
System.err.println("Error on inStream.readLine()");
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public boolean isProcessEnd() {
return processEnd;
}
public void setProcessEnd(boolean processEnd) {
this.processEnd = processEnd;
}
/*Readers of Inputs*/
class Input implements Runnable {
private BufferedReader inStream;
InputStream input;
Prompt parent;
public Input(Prompt prompt) {
// TODO Auto-generated constructor stub
parent = prompt;
}
public void run() {
inStream = new BufferedReader(new InputStreamReader(input));
while (!parent.isProcessEnd()) {
try {
String userInput;
while ((userInput = inStream.readLine()) != null) {
System.out.println(userInput);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/*Writers of Output*/
class Output implements Runnable {
OutputStream out;
Prompt parent;
public Output(Prompt prompt) {
parent = prompt;
// TODO Auto-generated constructor stub
}
#Override
public void run() {
while (!parent.isProcessEnd()) {
try {
String CurLine = "";
InputStreamReader converter = new InputStreamReader(
System.in);
BufferedReader in = new BufferedReader(converter);
while (!(CurLine.equals("quit"))) {
CurLine = in.readLine();
if (!(CurLine.equals("quit"))) {
out.write((CurLine + "\n").getBytes());
out.flush();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
You don't seem to be waiting for the child process to end so it is possible that the parent process ends before it gets a chance to read the output stream.
Here is an old but excellent article around Runtime.exec
http://www.javaworld.com/jw-12-2000/jw-1229-traps.html
The correct implementation is on this page
http://www.javaworld.com/jw-12-2000/jw-1229-traps.html?page=4
From what I can tell - there could be two problems here :
Are you trying to obtain the access to the stream BEFORE the child program has started reading ?
Are you running the parent process with insufficient access rights?
If you read a null from readLine() it means the peer has closed the stream. There was no output.