Extreme Java When vanilla Java is not enough

28Aug/080

IOException when loading a sound/midi from a JAR/ZIP archive

I have a MIDI file in a JAR archive. If I try to play it with the Sequencer class, I got an exception: "java.io.IOException: mark/reset not supported". I've found this related bug. I don't like workarounds (all bugs must die), but I developed this one:

public static InputStream loadStream(InputStream in) throws IOException {
  ByteArrayOutputStream bos = new ByteArrayOutputStream();
  byte[] buf = new byte[1024];
  int c;
  while ((c = in.read(buf)) != -1) {
    bos.write(buf, 0, c);
  }
  return new ByteArrayInputStream(bos.toByteArray());
}

With this method, I encapsulate the "unresetable" stream into a "resetable" ByteArrayInputStream.

21Aug/082

MQSeries not closing connections

I got this error while connecting to MQSeries:

MQJE001: An MQException occurred: Completion Code 2, Reason 2009
MQJE016: MQ queue manager closed channel immediately during connect
Closure reason = 2009

After some trial-and-error, I found the problem: MQ's InitialContext opens a connection, but only closes it if I close the IC itself:

ic.close();

Since my application creates a lot of instances of InitialContext, a lot of connections got leaked, giving that annoying error.

+1 to the IBM's hall-of-shame, section "useless error messages".

13Aug/082

Java2D Optimization (a.k.a "Java is NOT slow")

Playing around with Java2D, I created a little application that paints a lot of PNG images on screen (about 200). I use ImageIO to load them, but the first prototype was VERY slow (3fps maximum).

After reading about fullscreen exclusive mode API and some tips on graphics performance, I've created a BufferStrategy using the same snippet from its API. I got no improvement, but the code became a lot cleaner.

Then, I remembered my ancient days as a C programmer, where I always need to convert the image color format to the screen color format. Since I'm programming in Java, I created this snippet:

private static BufferedImage createCompatibleImage(BufferedImage img,
    boolean translucent) {
  GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment();
  GraphicsDevice d = e.getDefaultScreenDevice();
  GraphicsConfiguration c = d.getDefaultConfiguration();
  int t = translucent ? Transparency.TRANSLUCENT : Transparency.BITMASK;
 
  BufferedImage ret = c.createCompatibleImage(img.getWidth(),
    img.getHeight(), t);
 
  Graphics2D g = ret.createGraphics();
  g.drawImage(img, 0, 0, null);
  g.dispose();
  return ret;
}

Maybe there's a better way to copy the image, but the important part is to create an image with GraphicsConfiguration.

After this little trick, I got an impressive speed boost: from the 2fps-slow-motion-turtle to ludicrous 170fps (yes, one hundred seventy). I feel like saying: "It's over nine thousand!"