There are a few things to remember about java data types, to make this thing work.
I'm assuming you're using int variables because of the absence of explicit casts in your expression. If you're using an int type for your variables: data start_pos, and length; you should be using 32 instead of 16, since int's are 32-bit values.
Also if you're going to use integer primitive types like int, short or byte, remember that these primitive types are two's complement that are sign-extended, meaning that if you do a right shift on negative numbers like ~0 (evaluates to -1), ones will be appended on the higher order bit (sign bit) instead of zeroes.
For instance:
1111 1111 1111 1111 1111 1111 1111 1000
>>1
1111 1111 1111 1111 1111 1111 1111 1100
Now going back to your problem. The general idea is to be able to do a:
data & mask
Now, generating the mask is a bit tricky on signed data types. It would make sense to generate the mask using:
(~0 << (32 - length) >> (32 - length - start_pos))
But this won't work of course because of the sign extension.
I would suggest that instead of using right-shift >>, use rotate operator >>> that way instead of ones being appended on the higher order bit, the rotate operator will append the lower order bit.
For instance:
1111 1111 1111 1111 1111 1111 1111 1000
>>>1
0111 1111 1111 1111 1111 1111 1111 1100
so...
mask = (~0 << 32-length >>> 32-length-start_pos)
And your final answer would look something like:
(data & (~0 << 32-length >>> 32-length-start_pos)) >>> start_pos
The outermost rotate operation moves your masked data to the lower order bits.