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.
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".
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!"