Bitwise Operators

Although the examples here use 8-bit integers, Java integers are 32 bits. The highest bit is reserved for plus or minus sign. So you can set/unset 31 one-bit flags and a whole bunch of combination masks derived from the one-bit flag masks.

It is not recommended to use bitwise operations in routine application programming because the resulting code is not very easy to understand. The flow of logic is not obvious. Save bitwise operations for systems programming or where memory savings may be desired such as in a JavaCards.

Binary Math

Binary to Decimal Conversion

Hexadecimal to Decimal Conversion

3F = 3*16**1 + 15*16**0
= 63 (01111111 in binary)

Logical Bitwise Operations

bit 1

bit 2

OR (|)

AND (&)

XOR (^)

0

0

0

0

0

1

0

1

0

1

0

1

1

0

1

1

1

1

1

0

| (Bitwise OR) sets a bit to 1 if one or both of the corresponding bits in its operands are 1, and to 0 if both of the corresponding bits are 0. In other words, | returns one in all cases except where the corresponding bits of both operands are zero. The resulting bit pattern is the "set" (1 or true) bits of any of the two operands.This property is used to "set" or "turn on" a "flag" (bit set to one) in your flags or options variable regardless of whether that flag was set previously or not. Multiple flag bits can be set if a combo MASK is defined.

& (Bitwise AND) sets a bit to 1if and only if both of the corresponding bits in its operands are 1, and to 0 if the bits differ or both are 0. In other words, a oneANDed with any bit is that bit and a zeroANDed with any bit is zero. This operator is used to check the state of a flag in your flags variable. When you AND your flags variable with the MASK, all zeroes in the MASK will return zero for the corresponding position in flags and all ones in the MASK will return whatever the corresponding bit is set to in your flags variable. Therefore, the bitwise AND operator's evaluates to the MASK itself only if the MASK flags are also set in the flags variable.

// To check the state of a flag bit(s)
if ((flags & MASK) == MASK) {
// flag is set or turned on
...
}
else {
//flag is not set or is turned off
...
}

^ (Bitwise XOR or exclusive OR) sets the bit to 1 where the corresponding bits in its operands are different, and to 0 if they are the same. Even 1 ^ 1 evaluates to 0 unlike the regular Bitwise OR. A bit pattern XORed with itself returns zero (because same bit values return zero). The Bitwise XOR is used to toggle the flag bits of a MASK in your flags variable. It means that, if a flag bit was set in flags, XORing with its MASK will unset it. If it was not set, XORing will set it. This is different from turning a flag bit on or off, regardless of its prior state (which is accomplished using | and & ~).

// To toggle a flag bit(s) (on if it was off, off if it was on)
flags = flags ^ MASK;
// or, more succintly
flags ^= MASK;

~ (Bitwise NOT) takes only one parameter and inverts each bit in the operand, changing all the ones to zeros and zeros to ones. This is useful when "unsetting" or "turning off" a flag.

// To unset or turn off a flag bit(s)

flags = flags & ~MASK;
// or, more succintly
flags &= ~MASK;

Here, ~MASK turns all zeros to ones and all ones to zeros in MASK. flags & ~MASK leaves all the bits of flags as they are (one bit in the now-inverted MASK ANDed with any flags bit is that flags bit) except for the now-zeroed MASK bits. Zeroed MASK bits ANDed with any flags bit return zero, thereby unsetting the flag, regardless of its original value.

Typical Bit Mask Operations

Operation

Code

Set a flag or overlay multiple values

flags | flagbitN

Unset a flag (zero-out a bit or set a bit to zero)

flags & ~flagbitN

Check if a bit is set

(flags & flagbitN) == flagbitN

Invert a pattern of bits

~flags

Bit flags and bit masks use bitwise operators. A Java integer has 32 bits out of which 31 bits can be turned off or on to act as flag bits. (The highest order bit is reserved for plus or minus sign). A bit mask is simply a integer with one or more bits sets to 1. If you assign the integer any power of 2, it will set only one bit as 1 in the integer. Therefore, you initialize one-bit masks to powers of 2. Java integers can go from 2^^0 through 2^^30.

which sets the third bit from the right as the flag for VISIBLE, thus becoming a bit mask for the VISIBLE flag. Then you do bitwise operations to apply this mask on some flags (or options or status) variable to set, unset, check or toggle the VISIBLE flag bit in your flags variable.

Why the name Bit Mask?

When a bitwise AND is performed, the zeros in the MASK constant hide the corresponding bits in the your flags variable (because the result contains only the bits that are ones in both operands). You can think of the zeros in the MASK constant as being opaque and the ones as being transparent. Thus the expression flags & MASK is like covering the bit pattern of flags with the bit pattern of MASK so that only the bits under the ones of MASK are visible.

This mask leaves the final (low or right end) eight bits of the variable ch alone and sets the rest to zero. Thus, regardless of whether the original ch is 8, 16, 32 or more bits, the final value is trimmed down to fit into a single byte. This is useful:

For cross-platform development where the sizes of the primitive data types may vary between platforms.

When the operands to the binary bitwise operators are of different-sized data types.

The most common application of the bitwise operators is to set, clear, test and toggle individual bit flags using bit masks. One 32 bit Java integer can hold 31 individual flags (about 2**31 - 1 total combinations). The last bit on the left (the highest or most significant bit) is reserved for the + or - sign of the integer.

Bit masks can be used to store all the permissions granted to a database user as an integer in the permissions table.

Let's say that a user can be granted four types of permissions (in practice, there can be numerous types of permissions) - View, Add, Edit and Delete.

Desired User Permissions

User ID

View

Add

Edit

Delete

tom

Yes

No

No

No

dick

Yes

Yes

Yes

No

harry

Yes

Yes

Yes

Yes

It doesn't make sense to allow a user to add, edit or delete tables or rows if the user cannot view them. What we need are sets of valid permissions that a user may be granted.

No permission to do anything

View Only

View and Add

View and Edit

View, Add and Edit

All permissions (View, Add, Edit and Delete)

Using bit flags and masks, Each user's permission set can be stored as an integer in a simple key-value file or database. For very large systems or very small systems, this can significantly reduce the disk space needed.

How do we make sure that a user can only be assigned one of these permission sets? And how can we store permissions for numerous users for later access. We will investigate two ways of doing it - the application programming way and the system programming way.

Code Examples Using Bitwise Operators

There are two main Java code files below - BitwisePermissions.java and BooleanPermissions.java. The first one shows how to use bitwise Operators to set and unset various permission flags for database users. BooleanPermissions.java accomplishes exactly the same thing except that it uses Java booleans to represent flags.

On an average over 100's of tests, boolean version took about 50 percent longer to achieve same results.

Memory used by the boolean version was about 150 percent more than the memory used by the bitwise version.

Average time taken for testBitwiseOperations() = 1.62 millisecs
Free memory change for testBitwiseOperations() = -13656 bytes
Average time taken for testBooleanOperations() = 2.44 millisecs
Free memory change for testBooleanOperations() = -34024 bytes

Instead of using Java's System.out.println() method, the examples on this page use Apache Log4j's cat.info() methods to display output. To run the example code, you will need to put log4j.jar in Java's classpath. Alternatively, you may want to download the latest Log4j software (about 2.3MB as of log4j 1.1.3) and extract log4j.jar (about 156KB) out of it.

You will also need to save the following statements in a file named log4j.properties and place that file in a directory which is in Java's classpath so that Log4j can find this file and configure itself.

To measure performance of the code examples below, you will need to disable logging for every statement below the error as shown in the commented-out line above. Otherwise, the logging action itself takes too much time.

To not use Log4j, replace cat.info( with System.out.println( and delete import org.apache.log4j.*;

First of all, we will need DBSecurityException.java class to throw custom exceptions when the requested permissions do not make sense.

BitwisePermissions.java is the primary file which exercises bitwise operators. What we are doing here is trying to represent valid sets of database permissions as bit masks. This coding practice is used in systems level programming where speed and memory usage matters. A user can then be granted one of these valid permission sets. It needs Java 2 or higher because it uses the Arrays.

Okay, this one is a bit tricky. assign_permissions.java uses JUnit package to implement a testing class which exercises the two classes above. Basically, it extends JUnit's TestCase class, defines two methods - testBitwiseOperations() and testBooleanOperations() and runs these two methods repeatedly n2 number of times. You can change n2 value, recompile and run it. You may want to run with n2 = 1 and Log4j root category set to info. Then, you may want to run at n2 = 100 or something like that, but make sure that you set the Log4j root category to error, otherwise the tests will generate heaps of output and take forever to run. You, of course, need junit.jar in Java's classpath.