Java Fun: When 128 != 128 Thu, Feb 16. 2012
I didn't discover this, but I did think it was fun to share:
public class JavaWTF {
public static void main(String[] args) {
System.out.println(isSame(127, 127)); // true
System.out.println(isSame(128, 128)); // false
}
private static boolean isSame(Integer i1, Integer i2) {
return i1 == i2;
}
}
This is still true as of JDK 1.6. Why is this so? I took a look at the bytecode to see what's going on, and here's what we have:
Compiled from "JavaWTF.java"
public class JavaWTF extends java.lang.Object{
public JavaWTF();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: bipush 127
2: istore_1
3: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
6: new #3; //class java/lang/Integer
9: dup
10: iload_1
11: invokespecial #4; //Method java/lang/Integer."<init>":(I)V
14: new #3; //class java/lang/Integer
17: dup
18: iload_1
19: invokespecial #4; //Method java/lang/Integer."<init>":(I)V
22: if_acmpne 29
25: iconst_1
26: goto 30
29: iconst_0
30: invokevirtual #5; //Method java/io/PrintStream.println:(Z)V
33: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
36: iload_1
37: invokestatic #6; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
40: iload_1
41: invokestatic #6; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
44: if_acmpne 51
47: iconst_1
48: goto 52
51: iconst_0
52: invokevirtual #5; //Method java/io/PrintStream.println:(Z)V
55: return
}
(Incidentally, you can get this output by running javap -c JavaWTF.)
So basically, Integer.valueOf is being called to do the Integer boxing. From the 1.6 JavaDocs, I see:
So sometimes it returns cached values, and sometimes it doesn't. If this functions returns an Integer via new Integer all the time, then all == comparisons will fail. However, if it returns the same object for some invocations, we'll get the observed behavior.
At this point, I was stuck - I didn't know where to go to look at some real Java 6 source code, but I bet the Apache Harmony guys knew a thing or two about all the quirks of the Java platform, so I took a peak at their Integer.java class:
public static Integer valueOf(int i) {
if (i < -128 || i > 127) {
return new Integer(i);
}
return valueOfCache.CACHE [i+128];
}
static class valueOfCache {
/**
* <p>
* A cache of instances used by {@link Integer#valueOf(int)} and auto-boxing.
*/
static final Integer[] CACHE = new Integer[256];
static {
for(int i=-128; i<=127; i++) {
CACHE[i+128] = new Integer(i);
}
}
}
Ha! So I guess "most frequently used" integers means any integer between -128 and 127 (not integers your program has used before). No wonder!
public class JavaWTF {
public static void main(String[] args) {
System.out.println(isSame(127, 127)); // true
System.out.println(isSame(128, 128)); // false
}
private static boolean isSame(Integer i1, Integer i2) {
return i1 == i2;
}
}
This is still true as of JDK 1.6. Why is this so? I took a look at the bytecode to see what's going on, and here's what we have:
Compiled from "JavaWTF.java"
public class JavaWTF extends java.lang.Object{
public JavaWTF();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: bipush 127
2: istore_1
3: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
6: new #3; //class java/lang/Integer
9: dup
10: iload_1
11: invokespecial #4; //Method java/lang/Integer."<init>":(I)V
14: new #3; //class java/lang/Integer
17: dup
18: iload_1
19: invokespecial #4; //Method java/lang/Integer."<init>":(I)V
22: if_acmpne 29
25: iconst_1
26: goto 30
29: iconst_0
30: invokevirtual #5; //Method java/io/PrintStream.println:(Z)V
33: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
36: iload_1
37: invokestatic #6; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
40: iload_1
41: invokestatic #6; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
44: if_acmpne 51
47: iconst_1
48: goto 52
51: iconst_0
52: invokevirtual #5; //Method java/io/PrintStream.println:(Z)V
55: return
}
(Incidentally, you can get this output by running javap -c JavaWTF.)
So basically, Integer.valueOf is being called to do the Integer boxing. From the 1.6 JavaDocs, I see:
valueOf
public static Integer valueOf(int i)
Returns a Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values.
So sometimes it returns cached values, and sometimes it doesn't. If this functions returns an Integer via new Integer all the time, then all == comparisons will fail. However, if it returns the same object for some invocations, we'll get the observed behavior.
At this point, I was stuck - I didn't know where to go to look at some real Java 6 source code, but I bet the Apache Harmony guys knew a thing or two about all the quirks of the Java platform, so I took a peak at their Integer.java class:
public static Integer valueOf(int i) {
if (i < -128 || i > 127) {
return new Integer(i);
}
return valueOfCache.CACHE [i+128];
}
static class valueOfCache {
/**
* <p>
* A cache of instances used by {@link Integer#valueOf(int)} and auto-boxing.
*/
static final Integer[] CACHE = new Integer[256];
static {
for(int i=-128; i<=127; i++) {
CACHE[i+128] = new Integer(i);
}
}
}
Ha! So I guess "most frequently used" integers means any integer between -128 and 127 (not integers your program has used before). No wonder!
Goodbye wmii. Hello i3! Wed, Dec 21. 2011
A colleague recently recommend i3 to me, and I thought it was a rather good idea considering the problems I've been having with wmii (weirdly complicated configuration syntax, and problems with AWT).
wmii:

(Notice the dialog box is not rendered correctly on the bottom right)
i3:

The Swing problems are fixed in the HEAD of wmii's development branch, but I didn't notice that before I already committed to i3 (which is quite similar to wmii, but is less complicated to configure).
In the Debian/Ubuntu repositories, the latest version of i3 is 3.e (I think), but due to the configuration changes between 3 and 4, there may be some confusion about how to set up a status bar. The way to do it is to use i3status with the bar configuration directive with a 4.x+ release. You'll have to grab both i3wm and i3status from their respective repos and build the packages yourself. On Squeeze, apply this patch to i3 version 4.1 to make sure it builds correctly:
diff -rupN a/debian/control b/debian/control
--- a/debian/control 2011-11-11 14:40:38.000000000 -0800
+++ b/debian/control 2012-03-12 17:26:12.809273870 -0700
@@ -3,7 +3,7 @@ Section: utils
Priority: extra
Maintainer: Michael Stapelberg <michael@stapelberg.de>
DM-Upload-Allowed: yes
-Build-Depends: debhelper (>= 7.0.50~), libx11-dev, libxcb-util0-dev (>= 0.3.8), libxcb-ke
ysyms1-dev, libxcb-xinerama0-dev (>= 1.1), libxcb-randr0-dev, libxcb-icccm4-dev, libxcurso
r-dev, asciidoc (>= 8.4.4), xmlto, docbook-xml, pkg-config, libev-dev, flex, bison, libyaj
l-dev, texlive-latex-base, texlive-latex-recommended, texlive-latex-extra, libpcre3-dev, l
ibstartup-notification0-dev (>= 0.10)
+Build-Depends: debhelper (>= 7.0.50~), libx11-dev, libxcb-aux0-dev, libxcb-atom1-dev, lib
xcb-keysyms1-dev, libxcb-xinerama0-dev (>= 1.1), libxcb-randr0-dev, libxcb-icccm1-dev, lib
xcursor-dev, asciidoc (>= 8.4.4), xmlto, docbook-xml, pkg-config, libev-dev, flex, bison,
libyajl-dev, texlive-latex-base, texlive-latex-recommended, texlive-latex-extra, libpcre3-
dev, libstartup-notification0-dev (>= 0.10)
Standards-Version: 3.9.2
Homepage: http://i3wm.org/
You can apply this patch and build with:
$ cd i3-4.1
$ patch -p0 < /path/to/i3.patch
$ dpkg-buildpackage -uc -us
One other thing to note is that the i3status bar will not display correctly if there any errors; you also won't get any notification of errors if the font you specify is not correct (or missing).
Here is the result of switching to i3:

You can find my i3 configuration here.
wmii:
(Notice the dialog box is not rendered correctly on the bottom right)
i3:
The Swing problems are fixed in the HEAD of wmii's development branch, but I didn't notice that before I already committed to i3 (which is quite similar to wmii, but is less complicated to configure).
In the Debian/Ubuntu repositories, the latest version of i3 is 3.e (I think), but due to the configuration changes between 3 and 4, there may be some confusion about how to set up a status bar. The way to do it is to use i3status with the bar configuration directive with a 4.x+ release. You'll have to grab both i3wm and i3status from their respective repos and build the packages yourself. On Squeeze, apply this patch to i3 version 4.1 to make sure it builds correctly:
diff -rupN a/debian/control b/debian/control
--- a/debian/control 2011-11-11 14:40:38.000000000 -0800
+++ b/debian/control 2012-03-12 17:26:12.809273870 -0700
@@ -3,7 +3,7 @@ Section: utils
Priority: extra
Maintainer: Michael Stapelberg <michael@stapelberg.de>
DM-Upload-Allowed: yes
-Build-Depends: debhelper (>= 7.0.50~), libx11-dev, libxcb-util0-dev (>= 0.3.8), libxcb-ke
ysyms1-dev, libxcb-xinerama0-dev (>= 1.1), libxcb-randr0-dev, libxcb-icccm4-dev, libxcurso
r-dev, asciidoc (>= 8.4.4), xmlto, docbook-xml, pkg-config, libev-dev, flex, bison, libyaj
l-dev, texlive-latex-base, texlive-latex-recommended, texlive-latex-extra, libpcre3-dev, l
ibstartup-notification0-dev (>= 0.10)
+Build-Depends: debhelper (>= 7.0.50~), libx11-dev, libxcb-aux0-dev, libxcb-atom1-dev, lib
xcb-keysyms1-dev, libxcb-xinerama0-dev (>= 1.1), libxcb-randr0-dev, libxcb-icccm1-dev, lib
xcursor-dev, asciidoc (>= 8.4.4), xmlto, docbook-xml, pkg-config, libev-dev, flex, bison,
libyajl-dev, texlive-latex-base, texlive-latex-recommended, texlive-latex-extra, libpcre3-
dev, libstartup-notification0-dev (>= 0.10)
Standards-Version: 3.9.2
Homepage: http://i3wm.org/
You can apply this patch and build with:
$ cd i3-4.1
$ patch -p0 < /path/to/i3.patch
$ dpkg-buildpackage -uc -us
One other thing to note is that the i3status bar will not display correctly if there any errors; you also won't get any notification of errors if the font you specify is not correct (or missing).
Here is the result of switching to i3:
You can find my i3 configuration here.
Ditz bash completion Sun, Sep 18. 2011
I just had an "Oh, so that's how you do it" moment. The boss likes ditz for issue management; but for a while, I've been agonizing about how to do bash completion in ditz. The answer is you have to source this file: /var/lib/gems/1.8/gems/ditz-0.5/contrib/completion/ditz.bash. Oh, so that's how you do it!
Posted by Min Huang
Defined tags for this entry: git, programming
New layout! Sun, Sep 11. 2011
Getting my Logitech headset to work in Debian Thu, Jul 28. 2011
I'm on Debian Squeeze at work, and I don't have any external speakers, but I do want to use a USB headset for pair programming and meetings and such. Getting the headset to work with Skype actually pretty easy; you just do some clicky click GUI monkey business and you're set. But having sound play for Youtube and other video sites (you know, stuff to do when NOT in meeting or pair programming), is trickier than I thought.
Here's what I did. First figure out which number the headset is:
$ cat /proc/asound/cards
0 [Headset ]: USB-Audio - Logitech USB Headset
Logitech Logitech USB Headset at usb-0000:00:1d.1-1, full speed
1 [Intel ]: HDA-Intel - HDA Intel
HDA Intel at 0xfebdc000 irq 16
2 [HDMI ]: HDA-Intel - HDA ATI HDMI
HDA ATI HDMI at 0xfe9ec000 irq 17
Okay, so it's index 0. Then I made a new file called /etc/modprobe.d/sound and jammed this text in it:
options snd-usb-audio index=0
And then bingo bango bongo, there is sound in my Youtubes.
Here's what I did. First figure out which number the headset is:
$ cat /proc/asound/cards
0 [Headset ]: USB-Audio - Logitech USB Headset
Logitech Logitech USB Headset at usb-0000:00:1d.1-1, full speed
1 [Intel ]: HDA-Intel - HDA Intel
HDA Intel at 0xfebdc000 irq 16
2 [HDMI ]: HDA-Intel - HDA ATI HDMI
HDA ATI HDMI at 0xfe9ec000 irq 17
Okay, so it's index 0. Then I made a new file called /etc/modprobe.d/sound and jammed this text in it:
options snd-usb-audio index=0
And then bingo bango bongo, there is sound in my Youtubes.
« previous page
(Page 1 of 29, totaling 143 entries)
next page »

