I am using Swingworker to request value from url address to dynamically change a version of displayed information. At certain cases this worker is cancelled. The problem is that I get java.lang.InterruptedException sometimes (but not every time I cancel worker). I am not sure what to do with it, moreover I have no idea where it is thrown, I cannot debug it because I get it when I do lots of version changes in short time (I use slider and this happens when I am dragging it for some time) . Everything works fine but I get this annoying error:
java.lang.InterruptedException
at java.lang.Object.wait(Native Method)
at sun.plugin2.message.Queue.waitForMessage(Unknown Source)
at sun.plugin2.message.Pipe$2.run(Unknown Source)
at com.sun.deploy.util.Waiter$1.wait(Unknown Source)
at com.sun.deploy.util.Waiter.runAndWait(Unknown Source)
at sun.plugin2.message.Pipe.receive(Unknown Source)
at sun.plugin2.main.client.MessagePassingExecutionContext.doCookieOp(Unknown Source)
at sun.plugin2.main.client.MessagePassingExecutionContext.getCookie(Unknown Source)
at sun.plugin2.main.client.PluginCookieSelector.getCookieFromBrowser(Unknown Source)
at com.sun.deploy.net.cookie.DeployCookieSelector.getCookieInfo(Unknown Source)
at com.sun.deploy.net.cookie.DeployCookieSelector.get(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.setCookieHeader(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.writeRequests(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at org.dbwiki.web.applet.ValueRequester.doInBackground(ValueRequester.java:40)
at org.dbwiki.web.applet.ValueRequester.doInBackground(ValueRequester.java:1)
at javax.swing.SwingWorker$1.call(Unknown Source)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at javax.swing.SwingWorker.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Also after each exception which is showed above additional message is thrown:
sun.plugin2.main.client.PluginMain: unrecognized message ID 46
Interesting thing that exception is only being thrown when program is run in the browser as an applet, if program is run as applet from api no exceptions are thrown.
My StringWorker:
package org.dbwiki.web.applet;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import javax.swing.SwingWorker;
public class ValueRequester extends SwingWorker<Void, Void> {
HtmlGenerator htmlGen;
ArrayList<String[]> versionsData;
String id;
private String dbName;
ValueRequester (HtmlGenerator htmlGen, ArrayList<String[]> versionData, int ver){
try {
this.htmlGen=htmlGen;
if (TreeVisualiser.typeParameter.equals(TreeVisualiser.StructureVisualiserParameter))
this.id=htmlGen.getElem().getVersionElementId(ver);
else if(TreeVisualiser.typeParameter.equals(TreeVisualiser.HistoryVisualiserParameter))
this.id=htmlGen.getElem().getId();
this.dbName=htmlGen.getElem().getDBName();
this.versionsData=versionData;
} catch (Exception e) {
e.printStackTrace();
}
}
protected Void doInBackground() throws Exception {
try{
String value="";
URL historyURL = new URL("http://127.0.0.1:8080/"+dbName+id+"?value");
URLConnection hc = historyURL.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(hc.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
value+=line;
}
in.close();
this.htmlGen.formDisplayerHead();
this.htmlGen.formNodeDataHtml(value,this.versionsData);
this.htmlGen.formDisplayerTail();
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
protected void done()
{
if (!this.isCancelled())
this.htmlGen.dataDisplayer.setText(this.htmlGen.getHtml());
}
}
I have now idea what causes it, how to handle it or at least how to hide it (as everything works normal). Any help would be appreciated.
UPDATE:
I try to catch this exception in the ValueRequester.doInBackround(), however my catch statement don't catch the exception. My updated code of doInBackground():
protected Void doInBackground() throws Exception {
try{
String value="";
URL historyURL = new URL("http://127.0.0.1:8080/"+dbName+id+"?value");
URLConnection hc = historyURL.openConnection();
InputStream inputStrm=hc.getInputStream();
InputStreamReader inputStrmRdr= new InputStreamReader(inputStrm);
this.in = new BufferedReader(inputStrmRdr);
String line;
while ((line = in.readLine()) != null) {
value+=line;
}
this.htmlGen.formDisplayerHead();
this.htmlGen.formNodeDataHtml(value,this.versionsData);
this.htmlGen.formDisplayerTail();
}catch (InterruptedException e){
System.out.println("Interrupted Exception caught!");
// e.printStackTrace();
}
return null;
}
Unfortunately stack trace is still printed instead of my system out message. Any idea what could be wrong here?
As far as I know, an InterruptedException only occurs if some other thread calls Thread.interrupt() on a thread that is blocked. In this case, it is clear that the interrupted thread was in a wait() call at the time.
Looking at the SwingWorker code, it appears that the worker thread will get an interrupt if the thread that scheduled decides to call cancel(true) on it. Depending on what the worker thread is doing at the time, it may get an InterruptedException, or it may just have its Thread.interrupted flag set.
So the solution to your problem would appear to be to find out what is calling cancel(true) on the SwingWorker instance. Then either change it to not do that ... or make your worker class deal with the InterruptedException appropriately. The appropriate behaviour would probably be to catch the exception and quietly return from call(...)
To me it just looks like you are calling worker.cancel(true); (assuming worker is your SwingWorker). The true indicates that if the current Thread is in an interruptible state, the Thread can be interrupted. When this happens, it automatically throws an Exception indicating that the Thread has been interrupted allowing you to release resources and possibly do something. I guess in your case you can safely ignore this and simply close the opened streams.
In your case, depending on how far you are in your "Work", the task may get interrupted or not.
See more information on Thread interruption here.
Related
I am working on a simple Java messaging program. Before I begin working on more complex features, I would like to get the basic system working. Currently
Multiple clients can connect
Multiple clients can send messages that the server receives
Server closes connections when the client is terminates
This code in particular appears to be what is giving the errors. It is the run() method in my ClientThread.java thread (that implements runnable). This thread is for handling incoming messages from the server (sending messages works fine).
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class ClientThread implements Runnable{
private Socket server;
private DataInputStream in;
private DataOutputStream out;
public Text msgContent;
public void login(Stage stage, Scene main, String username, String password, String portString, String host) {
try {
int port = Integer.parseInt(portString);
this.server = new Socket(host, port);
this.in = new DataInputStream(server.getInputStream());
this.out = new DataOutputStream(server.getOutputStream());
stage.setScene(main);
Platform.runLater(new ClientThread());
}
catch (NumberFormatException e) {
System.out.println("Invalid Port");
return;
}
catch (IOException e) {
System.out.println("Error Connecting to Server");
return;
}
}
public void run() {
String msg = "";
try {
while (true) {
msg = in.readUTF(); //This line gives Errors
System.out.println("Read message from server");
msgContent.setText(msgContent.getText() + msg + "\n");
System.out.println("Added message from server to view");
}
}
catch(Exception ioe) {
ioe.printStackTrace();
System.out.println("Failed to read message from server and add to view.");
}
}
public void sendMsg(String msg) {
try {
out.writeUTF(msg);
} catch (Exception ioe) {
ioe.printStackTrace();
}
}
}
Note that msgContent is a Text object in my JavaFX frontend and in the inputStream from the server. My full code is here. The error I am getting is
java.lang.NullPointerException
at ClientThread.run(ClientThread.java:42)
at com.sun.javafx.application.PlatformImpl$6$1.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl$6$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl$6.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$300(Unknown Source)
at com.sun.glass.ui.win.WinApplication$4$1.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Failed to read message from server and add to view.
Also note that I am using Platform.runLater() to run this method. I want to know how to fix the above error so my code works. Thanks in advance.
Cause of NullPointer Exception
in is null.
Your NullPointerException occurs because in this call you create a new instance of the ClientManager class: Platform.runLater(new ClientThread());, so it won't use existing instance of ClientManager in which you have initialized the in and out members. Instead, you could use Platform.runLater(this);, to get rid of your NullPointerException.
However, your code has other issues...
Incorrect concurrent programming
You are hanging the JavaFX application thread which will stop your application from rendering or responding to UI input. Never busy wait the JavaFX application thread.
One way to accomplish what you are trying to do is to use the JavaFX concurrency utilities, in particular a Task.
Run the task on it's own thread, then it can loop, accepting input forever and it won't block your UI thread. You can (perhaps) make your thread a non-daemon thread so that it exits automatically when all of the other daemon threads complete. You could feed the input back to your UI using Platform.runLater. But, for the simple example you provided where you want to update some message text, instead you can invoke updateMessage (note this does not need a Platform.runLater call as the Task class takes care of that kind of detail for you). To get your message label updated, you can bind it's text property to the task's message property. There are examples of how to do this in the Task javadoc.
This bug occurs when my program enters the shutdown hook and tries to write the settings file to a text document. The strange thing is, it doesnt throw an exception everytime.
Exception in thread "Thread-4" java.lang.IllegalStateException: zip file closed
at java.util.zip.ZipFile.ensureOpen(Unknown Source)
at java.util.zip.ZipFile.getEntry(Unknown Source)
at java.util.jar.JarFile.getEntry(Unknown Source)
at java.util.jar.JarFile.getJarEntry(Unknown Source)
at com.crimson.server.JarClassLoader.findJarEntry(JarClassLoader.java:514)
at com.crimson.server.JarClassLoader.findJarClass(JarClassLoader.java:584)
at com.crimson.server.JarClassLoader.loadClass(JarClassLoader.java:956)
at java.lang.ClassLoader.loadClass(Unknown Source)
at com.crimson.universalUtils.Datastore.store(Datastore.java:66)
at com.crimson.server.ServerShutdownHook.run(ServerShutdownHook.java:38)
Here is Datastore.store(Settings):
public static File set = new File("settings.properties");
public static void store(Settings settings){
set.delete();
try {
set.createNewFile();
PrintWriter pw = new PrintWriter(set);//line 66
pw.println(ObjectTransfer.toString(settings));
pw.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I dont know why creating the PrintWriter calls ClassLoader.loadClass, but that could be the problem because im using JarClassLoader: http://www.jdotsoft.com/JarClassLoader.php
I checked the source code of JarClassLoader and the problem is that JarClassLoader also has a shutdown hook to close the jar file. And as the documentation of shutdown hooks says, they may be invoked in any order, or even in parallel. So when your hook "gets in" before JarClassLoaders, your code works. When it's a bit too late, you get this exception.
A way to get around this would be to ensure the PrintWriter class is loaded before invoking the shutdown hook.
I'm using the ARIN rest whois service to look up the organizations for a list of IP addresses. Since the list is very long (the one below is just a very small subset), I opted to do this with threads for faster performance.
public class SimpleThreadPool {
public final static String[] ips = {
"192.150.16.64","192.243.232.36","208.77.139.8","63.140.35.160",
"63.140.35.161","63.140.35.162","63.140.59.142","63.140.61.200",
"66.235.132.238","66.235.137.133","66.235.138.18","66.235.138.192",
"66.235.138.195","66.235.139.152","66.235.139.172","66.235.139.204",
"66.235.139.205","66.235.139.206","66.235.139.227","66.235.141.144",
"66.235.141.145","66.235.141.146","66.235.141.16","66.235.142.20",
"66.235.142.24","66.235.141.145","184.106.60.35","207.171.162.26",
"207.171.162.75","207.171.162.95","207.171.185.201","207.171.187.117",
"207.171.187.118","207.171.189.80","207.171.189.81","216.137.37.108",
"216.137.37.122","216.137.37.128","216.137.37.138","216.137.37.140",
"216.137.37.178","216.137.37.183","216.137.37.198","216.137.37.225",
"216.137.37.235","216.137.37.37","216.137.37.52","216.137.37.57",
"216.137.37.6","216.137.37.84"
};
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(4);
for (int i = 0; i < ips.length; i++) {
Runnable worker = new WorkerThread(ips[i]);
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {}
System.out.println("All threads finished.");
}
}
And here is WorkerThread:
public class WorkerThread implements Runnable {
private String workingIP;
public WorkerThread(String workingIP) {
this.workingIP = workingIP;
}
#Override
public void run() {
try {
URL url = new URL("http://whois.arin.net/rest/ip/" + workingIP);
InputStream inputStream = null;
HttpURLConnection con = (HttpURLConnection)(url.openConnection());
con.connect();
inputStream = con.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
String line = null;
while( (line=br.readLine()) != null )
{
if (line.contains("<td>Organization</td><td>")) {
String companyName = line.replace("<td>Organization</td><td>", "").trim();
System.out.println(workingIP + " maps to: " + companyName);
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
On my work machine (w/ an i5-2400, 4GB RAM, 32bit Win7), this code works fine all the way down to around the 45th+ IP address in the array. Then I get java.net.ConnectException errors thrown for the remaining lookups:
...
216.137.37.57 maps to: Amazon.com, Inc.
216.137.37.6 maps to: Amazon.com, Inc.
java.net.ConnectException: Connection timed out: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(Unknown Source)
at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at sun.net.NetworkClient.doConnect(Unknown Source)
at sun.net.www.http.HttpClient.openServer(Unknown Source)
at sun.net.www.http.HttpClient.openServer(Unknown Source)
at sun.net.www.http.HttpClient.<init>(Unknown Source)
at sun.net.www.http.HttpClient.New(Unknown Source)
at sun.net.www.http.HttpClient.New(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source)
If I change the executor's thread pool size to 1, then everything works and no errors are thrown, but obviously the lookups take a lot longer.
The really strange thing is that if I run this same code on my 2011 Core i7 Mac, no errors whatsoever are thrown. Granted, the two are on different networks (my work machine uses my work's network, while my Mac is wirelessly tethered to a smartphone).
Any idea what's going on here, and what I can do to fix it?
You need to write sane error-handling code. It really is that simple. What do you want to do if the connection times out? If you make a lot of connections at once on a slow network, some of them may time out.
I am running in to some trouble when shutting down the server component and was hoping to get some help.
My server code looks as follows, it has a method to shut down the server
Server
private final String address = "127.0.0.1";
private Registry registry;
private int port = 6789;
public RmiServer() throws RemoteException {
try {
registry = LocateRegistry.createRegistry(port);
registry.rebind("rmiServer", this);
} catch (RemoteException e) {
logger.error("Unable to start the server. Exiting the application.", e);
System.exit(-1);
}
}
public void shutDownServer() throws RemoteException {
int succesful = 0;
try {
registry.unbind("rmiServer");
UnicastRemoteObject.unexportObject(this, true);
Thread.sleep(1000);
} catch (NotBoundException e) {
logger.error("Error shutting down the server - could not unbind the registry", e);
succesful = -1;
} catch (InterruptedException e) {
logger.info("Unable to sleep when shutting down the server", e);
succesful = -1;
}
catch (AccessException e) {
logger.info("Access Exception", e);
succesful = -1;
}
catch (UnmarshalException e) {
System.out.println(e.detail.getMessage());
logger.info("UnMarshall Exception", e);
succesful = -1;
}
catch (RemoteException e) {
System.out.println(e.detail.getMessage());
logger.info("Remote Exception", e);
succesful = -1;
}
logger.info("server shut down gracefully");
System.exit(succesful);
}
My client connects fine, no issues, so to shutdown i created a new application, copied the client code to connect and then call the close method on the server
Shutdown
public class Shutdown {
private String serverAddress = "127.0.0.1";
private String serverPort = "6789";
private ReceiveMessageInterface rmiServer;
private Registry registry;
public Shutdown(){
try {
registry = LocateRegistry.getRegistry(serverAddress, (new Integer(serverPort)).intValue());
rmiServer = (ReceiveMessageInterface) (registry.lookup("rmiServer"));
logger.info("Client started correctly");
rmiServer.shutDownServer();
System.exit(0);
}
catch (UnmarshalException e ){
logger.error("Unmarshall exception. Exiting application", e);
System.exit(-1);
}
catch (RemoteException e) {
logger.error("Remote object exception occured when connecting to server. Exiting application", e);
System.exit(-1);
} catch (NotBoundException e) {
logger.error("Not Bound Exception occured when connecting to server. Exiting application", e);
System.exit(-1);
}
}
No matter what i try i keep getting the following exception;
ERROR com.rmi.client.RMIClient - Unmarshall exception. Exiting application
java.rmi.UnmarshalException: Error unmarshaling return header; nested exception is:
java.net.SocketException: Connection reset
at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source)
at sun.rmi.server.UnicastRef.invoke(Unknown Source)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unknown Source)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source)
at $Proxy0.shutDownServer(Unknown Source)
at com.rmi.shutdown.Shutdown.<init>(Shutdown.java:31)
at com.rmi.shutdown.Shutdown.main(Shutdown.java:52)
Caused by: java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.io.BufferedInputStream.fill(Unknown Source)
at java.io.BufferedInputStream.read(Unknown Source)
at java.io.DataInputStream.readByte(Unknown Source)
... 7 more
I belive this might be due to the fact that the client is not properly disconnected and just gets "cut off" but i am unsure how else to disconnect the server side?
please can some one advise.
thanks
Unexport with force = true doesn't abort calls in progress. In general it will let in-progress calls run to completion. Your shutDownServer method is almost correct in that it unregisters the remote reference and unexports it. What it does next doesn't work, though. First, it sleeps for one second. This keeps the call in progress and keeps the client waiting for a reply. Then the shutdown code exits the server JVM without returning from the remote call. This closes client's connection while it's still awaiting a reply. That's why the client gets the connection reset exception.
To shut down cleanly, unregister the remote object, unexport it with force = true (as you've done) and then simply return. This will send a reply to the client, letting its remote call complete, and it will then exit. Back on the server, after the last in-progress call has completed, if there are no other objects exported, and if there's nothing else keeping the JVM around (such as non-daemon threads) the JVM will exit. You need to let RMI finish up its server-side processing instead of calling System.exit().
The system is doing exactly what you told it to do. You told it to unexport itself, and you set the 'force' parameter to true, which aborts calls in progress, so it unexported itself and aborted the call in progress. Just ignore it, or if you insist on a clean response to the shutdown client, have the server start a new thread for the unexport operation, with a short delay so the shutdown call can return to the client.
I just learned how to use threads yesterday and I'm trying to encode some images using threads but I'll get this error
java.lang.IllegalArgumentException: im == null!
I tried doing this exact same thing without threads and it worked fine just kind of slowly, not because of the image io but because of the time it takes to encode images.
the WinDef.HDC is a variable type I got from the JNA library. When I did try it without threads I could easily write out 1000 images (about 60mb).
//The thread class
public class imageEncoderThread extends Thread {
HDC originalImage;
BufferedImage image;
public imageProcessThread (HDC rI) {
originalImage = rI'
}
#Override
public void run() {
//returns a buffered image
image = process(rawImage);
try {
ImageIO.write(image, "jpg", new File (filePath));
} catch (IOException e) {
}
}
}
//full stack trace
Exception in thread "Thread-5" java.lang.IllegalArgumentException: im == null!
at javax.imageio.ImageIO.write(Unknown Source)
at javax.imageio.ImageIO.write(Unknown Source)
at com.capture.SingleImageEncoderThread.run(Thread.java:33)
Exception in thread "Thread-7" java.lang.IllegalArgumentException: im == null!
at javax.imageio.ImageIO.write(Unknown Source)
at javax.imageio.ImageIO.write(Unknown Source)
at com.capture.SingleImageEncoderThread.run(Thread.java:33)
Exception in thread "Thread-6" java.lang.IllegalArgumentException: im == null!
at javax.imageio.ImageIO.write(Unknown Source)
at javax.imageio.ImageIO.write(Unknown Source)
//and so on with the same exception
It's almost certainly the case that you cannot call:
image = JNAScreenShot.encodeRawWindow(rawImage, bounds);
from any thread other than the main ui thread. See:
http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/6398cda5-5393-4b16-b8dc-5bbf8902033f/ (specifically, I do not think HDCs are usable outside the main ui thread).
So, you'll need to create the screenshot first, then pass it to your thread to do the IO (that's probably the slow part, anyway).