Well, the basic problem is that some Java VM implementations use the same Java thread to do everything.
One of the first thing you need to figure out about the threading model of your VM is who developed it.
There is a list of J2ME licensees here: http://java.sun.com/javame/licensees/index.jsp
From that information, try to figure out how many native threads your VM is using. The 2 usual models are either run all bytecode interpretation into one native thread or run each java thread into its own native thread.
The next step is to gather information about how asynchronous the underlying operating system APIs are. When developing the VM, the licensees would have had to write native code to port the VM to the operating system. Any Inter-Process Communication or use of slow transmission medium (from flash card to GPS signal) might be implemented using a separate native thread that could allow the bytecode interpreter thread to keep running while the system waits for some data.
The next step is to realize how badly implemented the VM is. Typically, your problem happens when the VM uses only one internal java thread for all callbacks methods in the MIDP spec. So, you don't get a chance to react to keypad events until after your connection is opened is you try to open it in the wrong java thread.
Worse, you can actually prevent the screen from being refreshed because Canvas.paint() would be called in the same java thread as javax.microedition.media.PlayerListener.playerUpdate() for example.
From the VM implementation perspective, the golden rule is that any callback that you don't control (because it can end up in "user" code, like a listener) cannot be called from the same java thread you use unblock standard API calls. A lot of VM out there simply break that rule, hence the Sun recommendation that JavaME developers work around it.