JasonN JasonN - 2 months ago 11
Java Question

Ideas to deal with "unsigned" integers in Java 8

I'm working on code that is hardware and and math related and makes extensive use of unsigned integer values, 32- and 64-bit. Bugs have been steady and difficult to work through without any javac support. Java 8 added a few functions on the boxed Long class for division, mod, and comparisons, but while these provide run-time support, the lack of compile-time warnings for unintended mixing of the two has made me want to pull my hair out.

Does anybody know of any ways to help deal with these issues? One of the Java team members mentions possible annotation support for type checking.

So far, I prefix all unsigned variables with u_, and I even tried adding an

/* unsigned */
comment before each occurance of
int
or
long
that should be unsigned. While these were useful, they were also extremely cluttering. It doesn't go far enough. There are just too many opportunities for mistakes.

Two of the larger problems are unwanted sign extension and mixed operations.

Something as innocuous as
/* unsigned */ long u_lowmask = 0xffffffff
does not have the desired result or even just
/* unsigned */ long u_widen64 = small32
ruins things with that silent extension. In other languages I can get warnings from the compiler or Lint-like static checker. Functional languages often build it into the type checking mechanism, but Java has eschewed these in favor of other solutions. There is just so many chances for a mixed comparison or operations.

Any ideas should hopefully have no runtime impact, so I can't afford wrapping unsigned in a class or bignums. Well, I might be able to wrap them in a class if I could get away with doing it without any allocation or the expense of thread locals, but this would probably make the code non-reentrant. Also Hotspot would have to be able to emit code for the wrapped unsigned integers close to simple native. (Actually, I think Hotspot is probably smart enough to get close - maybe an extra memory read and write.)

How are other people coding around this issue?

Answer Source

EDIT: As of July 2016, the Checker Framework ships with much or all of what you are asking for: the Signedness Checker, which verifies consistent use of signed vs. unsigned values. From the manual:

The Signedness Checker guarantees that signed and unsigned values are not mixed together in a computation. In addition, it prohibits meaningless operations, such as division on an unsigned value.

(Hat tip to @MAGx2 for noticing that this answer was out of date.)


Older answer follows:

I suggest that you look into the Checker Framework. It enables you to define your own type qualifier annotations such as @Unsigned, and then to check at compile time that your code is type-correct with respect to these annotations. If it issues no warnings, then you have a guarantee that your code doesn't mix signed and unsigned values.

The Checker Framework ships with 20 type-checkers, but not one for unsigned arithmetic. You would need to write your own type-checker. This should be relatively straightforward since the type-checker would need few special rules: you just don't want to mix signed and unsigned values.

For a list of JDK methods that need library annotations, see http://hg.openjdk.java.net/jdk8/tl/jdk/rev/71200c517524