Java – J2ME networks, threads and deadlocks
The simple MIDlet code (class MOO) is locked (after excerpt) (at least I think it is locked after reading this article on thread here)
I reprinted the relevant excerpt of the post:
String url = ... Connection conn = null; try { conn = Connector.open( url ); // do something here } catch( IOException e ){ // error }
The root of the problem is the blocking nature of the open () call On some platforms, the system actually connects under the cover, which is equivalent to a separate thread The calling thread blocks until the connecting thread establishes a connection At the same time, the security subsystem may require the user to confirm the connection, and the connection thread is blocked until the event thread is confirmed by the user The deadlock occurs because the event thread is already waiting for the connection thread
public class Moo extends MIDlet { protected void destroyApp(boolean arg0) throws MIDletStateChangeException { // TODO Auto-generated method stub } protected void pauseApp() { } protected void startApp() throws MIDletStateChangeException { Display display = Display.getDisplay(this); MyCanvas myCanvas = new MyCanvas(); display.setCurrent(myCanvas); myCanvas.repaint(); } class MyCanvas extends Canvas { protected void paint(Graphics graphics) { try { Image bgImage = Image.createImage(getWidth(),getHeight()); httpconnection httpconnection = (httpconnection) Connector .open("https://stackoverflow.com/content/img/so/logo.png"); Image image = Image.createImage(httpconnection .openInputStream()); bgImage.getGraphics().drawImage(image,0); httpconnection.close(); graphics.drawImage(bgImage,0); } catch (IOException e) { e.printStackTrace(); } } } }
Someone can tell me how to complete system thread calls (event and notification threads) and the sequence of events that cause deadlock here I don't know what the thread causing deadlock is
>Is there documentation on the J2ME threading model? > Where can I get the source code of J2ME system class (I want to see the implementation of connection class)?
Editor: in the above code, I got the logic But should the following code at least work? This also deadlocks where I make a network connection in a separate thread
public class Foo extends MIDlet { protected void destroyApp(boolean arg0) throws MIDletStateChangeException { // TODO Auto-generated method stub } protected void pauseApp() { // TODO Auto-generated method stub } protected void startApp() throws MIDletStateChangeException { Display display = Display.getDisplay(this); MyCanvas myCanvas = new MyCanvas(); display.setCurrent(myCanvas); myCanvas.repaint(); } class MyCanvas extends Canvas { protected void paint(Graphics graphics) { try { Image bgImage = Image.createImage(getWidth(),getHeight()); FetchImage fetchImage = new FetchImage(); Thread thread = new Thread(fetchImage); thread.start(); thread.join(); bgImage.getGraphics().drawImage(fetchImage.image,0); graphics.drawImage(bgImage,0); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public class FetchImage implements Runnable { public Image image; public void run() { httpconnection httpconnection; try { httpconnection = (httpconnection) Connector .open("http://10.4.71.200/stage/images/front/car.png"); image = Image.createImage(httpconnection.openInputStream()); httpconnection.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
Solution
You can't It actually relies on suppliers Nokia may deal with this situation differently from Motorola
The lesson you must learn is not to make expensive calculations in system callbacks, as this may make the system unresponsive Therefore, time - consuming operations are placed in a separate thread and returned from the callback as early as possible
Even if you create a separate thread in the second example, you have to wait for it to complete in paint (), which will eventually lead to no thread!
One thing you can do is
class MyCanvas extends Canvas { Image image; boolean imageFetchFailed; protected void paint(Graphics g) { if (image == null) { fetchImage(); g.drawString("Fetching...",getWidth() >> 1,getHeight() >> 1,Graphics.HCENTER | Graphics.TOP) } else if (imageFetchFailed) { g.drawString("Failed to fetch image",Graphics.HCENTER | Graphics.TOP) } else { g.drawImage(image,0); } } private void fetchImage() { new Thread(new Runnable() { public void run() { httpconnection httpconnection = null; try { httpconnection = (httpconnection) Connector .open("http://10.4.71.200/stage/images/front/car.png"); image = Image.createImage(httpconnection.openInputStream()); } catch (IOException e) { e.printStackTrace(); imageFetchFailed = true; } if (httpconnection != null) { try { httpconnection.close(); } catch (IOException ignored) { } } // Following will trigger a paint call // and this time image wont be null and will get painted on screen repaint(); } }).start(); } }