Weird corruption of Boolean Array in Java - java

This might sound weird but I am struggling with this bug for past 2 days.
I have a boolean array in java that is initialised using a Random boolean generator.
After that the boolean array is acted upon by a function in C (called using JNI) and the modified boolean array is returned to java. When I hand over the boolean array to C, it is converted to unsigned char and converted back to jbooleanArray before being handed back to java.
Now I run the following code (there is a for loop over i):
if(chosen_packet[i] == false)
{
pkt.first[i] = 0;
System.out.print(chosen_packet[i]);
}
if(chosen_packet[i] == true)
{
pkt.first[i] = 1;
System.out.print(chosen_packet[i]);
}
The problem is that sometimes when chosen_packet[i] is true it still does not enter the second if condition. This happens sometimes and sometimes the code works just fine. When I print chosen_packet[i] in such a case it is printed as true yet it does not enter the second if condition. What could be the possible reason for this seeming corruption of the boolean array ?
EDIT: This is how I convert the boolean array to unsigned char in C:
jboolean *element = (*env)->GetBooleanArrayElements(env,chosen_packet,0);
for(j = 0; j < sz; j++)
src_pkt[j] = (unsigned char)element[j];
This src_pkt is acted upon and then I convert it back to jboolean .
EDIT2: This is how I convert the unsigned char array back to jboolean:
jbooleanArray arr = (*env)->NewBooleanArray(env,sz);
(*env)->SetBooleanArrayRegion(env,arr,0,sz,src_pkts);
(*env)->DeleteLocalRef(env,arr);

It's normal that if the boolean is true it does not enter in the first if since you are checking for it to be false in its condition.
Your code can be simplified to (you should use if/else instead of two if checking for the different conditions).
if (chosen_packet[i]) {
pkt.first[i] = 1;
} else {
pkt.first[i] = 0;
}
System.out.print(chosen_packet[i]);
or even
pkt.first[i] = chosen_packet[i] ? 1 : 0;
System.out.print(chosen_packet[i]);
Edit
If your program does not enter the second if, it means that the the var chosen_packet[i] is not true, you could use a debugger to verify what is the real value.
As stated by fredcrs, are you sure that chosen_packet[i] is of type boolean?

Java boolean is usually implemented as single byte. So it is possible that there is a bug in your C code that causes the boolean to be neither true nor false. In that case you may encounter undefined behavior.
Note that simply casting unsigned char to jboolean as in(jboolean) src_pkt[j] does not normalize it. You have to use src_pkt[j] ? JNI_TRUE : JNI_FALSE.
Still I believe you have to post more of relevant parts of your JNI code.

Related

Why does Java integer act erroneously at values near 2^31-1?

I'm trying to write a Java program to calculate the square root of an integer x, without using in-built functions like Math.pow() . This is the approach I tried -
class Solution {
public int mySqrt(int x) {
if(x==0 || x==1)
return x;
// if(x>=2147395600)
// return 46340;
int i;
for(i=1 ; i*i<=x ; i++) {}
return i-1;
}
}
Without the commented part, I start getting errors if x is in the range 2147395600 <= x <= 2^31-1 (which is the upper limit of an int's value range in Java). For instance, for the input x=2147395600, the expected output is 46340 but the actual output is 289398. Why is this happening? Thanks to all in advance.
PS - I am aware there are other (better) methods to solve this problem, but I'd really like to know why this code behaves this way.
Since 46340 * 46340 = 2147395600, when i=46340, x=2147395600 and you reach the condition i*i<=x it evaluates to true since 2147395600 = 2147395600. So the loop counter will incremnet by 1 and in the next iteration we will get i=46341 and i * i will cause an overflow - 46341*46341 = -2147479015.
The loop condition will still be true, since -2147479015 <= 2147395600, and the loop will not stop.
You can replace the <= with =, and check for edge cases that may occur now.

Treating an integer as a boolean in Java

I'm working on updating an old Java application to work on modern operating systems and I've run into an error that I can't figure out. I don't have much experience with Java but from what I've read, you can't store boolean values in an integer (1 or 0) like in C++.
Here's the bit of code where the error is:
public static double a(cr paramcr, int paramInt) {
double d = 0.0D;
int i = ++b;
if (b <= l.length()) {
if (paramInt < 0) {
int j = b; // <----------- defined again as an integer.
d = e();
if (e == true && d >= h && d + f - g >= 1.0D && d + f - g <= d) {
String str1 = String.valueOf((int)d);
d = d + f - g;
String str2 = String.valueOf((int)d);
l = a(j, l, str1, str2, i);
} else if (j == false) { // <---------------------------- error
if (((d < 1.0D || d > d) ? false : true) == false)
c = 7;
}
With error message:
The operator == is undefined for the argument type(s) int, boolean
The variable j is defined as a static boolean at the top of the program, but later redefined as an integer inside of this 'a' class. I notice that there are other integer variables being used to compare to true and false statements in this class, but they are all being compared to some condition in order to get a true or false result. That's obviously not the case here, and my problem is that I can't think of a way that this program would have ever functioned in the past if this is how it was written. Any ideas as to why this could be or suggestions on my next move?
It doesn't help that none of this has any documentation or intuitive variable names.
In Java you cannot treat an int as a boolean. Period.
I was sent some files that I was told contained the source code. It did not. I was then told to decompile it.
What you are apparently looking at is some code that has been decompiled from a ".class" file. Decompilation is NOT guaranteed to produce valid (compilable) Java source code. And in this case, it appears that it hasn't. Indeed, there are clues in that code that imply that the original bytecodes were obfuscated ... to deliberately make it hard for the decompiler to generate readable / valid Java source code.
(The problem is that the same bytecodes are used dealing with boolean and integer types up to int. In this case, the decompiler has assumed that the local variable is an int, and not been able to figure out that its assumption was incorrect. A better decompiler might be able to figure it out ...)
So what you will need to do is figure out how to modify that (not-really-Java) code to make it 1) compilable, and 2) do the correct thing1.
It doesn't help that none of this has any documentation or intuitive variable names.
Well ... that what happens when you try to use decompiled code. All local variable names and comments (including javadocs) are discarded by the compiler, and the decompiler has no way to reconstruct them.
The alternative is to go back to the people who were supposed to give you the source code and ask them to provide it to you ... for real!
1 - This assumes that you can figure out what this method is really supposed to be doing. I don't think we can help you with that. For a start, it would probably be necessary to read the disassembled bytecodes to figure out what the code really does.

As a newbie I can't find the bug in the program

I was training a code wars kata and the kata was:
In a factory a printer prints labels for boxes. For one kind of boxes the printer has to use colors which, for the sake of simplicity, are named with letters from a to m.
The colors used by the printer are recorded in a control string. For example a "good" control string would be aaabbbbhaijjjm meaning that the printer used three times color a, four times color b, one time color h then one time color a...
Sometimes there are problems: lack of colors, technical malfunction and a "bad" control string is produced e.g. aaaxbbbbyyhwawiwjjjwwm with letters not from a to m.
You have to write a function printer_error which given a string will output the error rate of the printer as a string representing a rational whose numerator is the number of errors and the denominator the length of the control string. Don't reduce this fraction to a simpler expression.
The string has a length greater or equal to one and contains only letters from a to z.
Examples:
s="aaabbbbhaijjjm"
error_printer(s) => "0/14"
s="aaaxbbbbyyhwawiwjjjwwm"
error_printer(s) => "8/22"
and as a newbie, I tried to attempt it . My program is like this:
public class Printer {
public static String printerError(String s) {
int printErr = 0;
char end = 110;
int i = 0;
while (i < s.length()){
if(s.charAt(i) > end ){
printErr++;
}
i++;
}
String rate = String.format("%d/%d",printErr , s.length());
return rate;
}
}
It passed the test but while submitting the Kata the counter was missing 1 or 2 numbers. Can anyone help?
You can actually just use < and > to check if a character is in some range in java. Your logic is sound - but since you are a "newbie", you have re-created the functionality of a for-loop with your while loop. No need to do this - that's why we have for-loops.
See the adjusted method below:
public String printerError(String s) {
int printErr = 0;
for (int i = 0; i < s.length(); i++) {
// assuming the input rules hold true, we really only need the second condition
if (s.charAt(i) < 'a' || s.charAt(i) > 'm') {
printErr++;
}
}
return String.format("%d/%d", printErr, s.length());
}
This is an answer from one newbie to another :p, so my answer may be a little wrong. As far as I have understood, you have committed a silly logical error within the if-condition.
if(s.charAt(i) > end )
You have used ASCII values, which is assigned as follows: a-97, b-98, c-99..., m-109.
Note that you are counting it error only if the ASCII value of character is more than 110, meaning that your code will accept 'n' (whose ASCII value is 110) to be valid. That might be the only reason why your counter would store a wrong value.

Trying to convert a bunch of C++ codes into Java - if statement

i was trying to write some C++ codes into java, now i have writter following code into java but it is throwing errors!
if(ShapeNotFound && xd*yd - nPixel[k] < xd+yd) // Condition for RECTANGLE
{
System.out.print("\n "+in+" \t Rectangle \n");
fileWriter3.write("\n "+in+" \t Rectangle \n");
Shape[k] = 2;
ShapeNotFound = 0;
}
I am getting following error :
The operator && is undefined for the argument type(s) int, boolean
Please help, tell me how to write the above if condition correctly in java
C and C++ both assume that for integers 0 is false and all other values are true.
Java does not make the same assumption so you need to add a check for int!=0 into the expression i.e.:
if((ShapeNotFound!=0) && (xd*yd - nPixel[k] < xd+yd))
Or alternatively your ShapeNotFound variable should be of type boolean not int.
It would be worth converting variable names etc to Java style guidelines as well.
Java can not convert int into boolean automatically.
It looks like ShapeNotFound is an integer, but you're implicitly treating it like a boolean (true or false). Java only likes genuinely boolean expressions, so you'll need to change the condition to something like this:
if (ShapeNotFound != 0 && xd*yd - nPixel[k] < xd+yd)
For readability, I'd suggest putting some brackets round each part of the condition. That's an issue of personal preference though.

Converting Boolean to Integer in Java without If-Statements

I'm wondering if there's a way to convert a boolean to an int without using if statements (as not to break the pipeline). For example, I could write
int boolToInt( boolean b ){
if ( b )
return 1
return 0
But I'm wondering if there's a way to do it without the if statement, like Python's
bool = True
num = 1 * ( bool )
I also figure you could do
boolean bool = True;
int myint = Boolean.valueOf( bool ).compareTo( false );
This creates an extra object, though, so it's really wasteful and I found it to be even slower than the if-statement way (which isn't necessarily inefficient, just has the one weakness).
You can't use a boolean other than in a if. However it does not mean that there will be a branch at the assembly level.
If you check the compiled code of that method (by the way, using return b ? 1 : 0; compiles to the exact same instructions), you will see that it does not use a jump:
0x0000000002672580: sub $0x18,%rsp
0x0000000002672587: mov %rbp,0x10(%rsp) ;*synchronization entry
0x000000000267258c: mov %edx,%eax
0x000000000267258e: add $0x10,%rsp
0x0000000002672592: pop %rbp
0x0000000002672593: test %eax,-0x2542599(%rip) # 0x0000000000130000
; {poll_return}
0x00000000025b2599: retq
Note: this is on hotspot server 7 - you might get different results on a different VM.
Use the ?: operator: ( b ? 1 : 0 )
You can use the ternary operator:
return b ? 1 : 0;
If this is considered an "if", and given this is a "puzzle", you could use a map like this:
return new HashMap<Boolean, Integer>() {{
put(true, 1);
put(false, 0);
}}.get(b);
Although theoretically the implementation of HashMap doesn't need to use an if, it actually does. Nevertheless, the "if" is not in your code.
Of course to improve performance, you would:
private static Map<Boolean, Integer> map = new HashMap<Boolean, Integer>() {{
put(true, 1);
put(false, 0);
}};
Then in the method:
return map.get(b);
Otherwise, you could use the Apache Commons BooleanUtils.toInteger method which works like a charm...
// Converts a boolean to an int specifying the conversion values.
static int toInteger(boolean bool, int trueValue, int falseValue)
// Converts a Boolean to an int specifying the conversion values.
static int toInteger(Boolean bool, int trueValue, int falseValue, int nullValue)
I found a solution by framework. Use compare for Boolean.
// b = Your boolean result
// v will be 1 if b equals true, otherwise 0
int v = Boolean.compare(b, false);
This is not directly possible, not in Java anyway. You could consider directly using an int or byte instead of a boolean if you really need to avoid the branch.
It's also possible that the VM is smart enough to eliminate the branch (the if or ?:) itself in this case, as the boolean's internal representation is quite likely to be the literal 1 or 0 anyway. Here is an article on how to examine the generated native machine code for the Oracle JDK, and if you need speed, make sure you're using the "server" JVM as it performs more aggressive optimization than the "client" one.
I can't say I recommend this. It's both slower than the ternary operator by itself, and it's too clever to be called good programming, but there's this:
-Boolean.FALSE.compareTo(value)
It uses the ternary under the covers (a couple of method calls later), but it's not in your code. To be fair, I would be willing to bet that there's a branch somewhere in the Python execution as well (though I probably only bet a nickel ;) ).
Since you want no if / else solution your expression is perfect, though I would slightly change it
int myint = Boolean.valueOf( bool ).compareTo( Boolean.FALSE );
There is no object creation involved, Boolean.valueOf(boolean b) returns either Boolean.TRUE or Boolean.FALSE, see API
A reasonable alternative to ising to the ternary to avoid an "if":
private static Boolean[] array = {false, true};
int boolToInt( boolean b ){
return Arrays.binarySearch(array, b);
}
Note that I consider this s "puzzle" question, so if coding it myself i would use the ternary..
You can try using ternary operator like this
int value = flag ? 1 : 0;
Nowadays, jdk has delivered a useful Utils method: BooleanUtils.toInteger()
In the source code, the method that jdk realize it must be efficient:
public static int toInteger(boolean bool) {
return bool ? 1 : 0;
}
So, I think the most votes answer is very great, return bool ? 1 : 0 is the best practice.
Example Code to use BooleanUtils as followed:
BooleanUtils.toInteger(false);
int ansInt = givenBoolean ? 1 : 0;

Categories

Resources