Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Method should return boolean, returns int

I have to create a method similiar to one that's inside a JAR. I have no code, so I disassabled to study. I used JD-GUI, which tells me, is:

private static boolean checkMe(Date paramDate, String paramString)
        throws REUException {
    int i = 1;
    int j, k;

    // unrelated stuff

    if (j > k)
        i = 0;
    return i;
}

You can see in method signature it should return a boolean, but it really returns an ìnt, which is not allowed in Java
So, I thought there were something wrong with JD-GUI.

I tried to dissasemble using javap, but I still don't get a clue:

Using: javap -c -s -verbose -private Class

I get:

private static boolean checkMe(java.util.Date, java.lang.String)   throws reu.exceptions.REUException;
  Signature: (Ljava/util/Date;Ljava/lang/String;)Z
  Code:
   Stack=4, Locals=7, Args_size=2
   0:   iconst_1
   1:   istore_2
   2:   getstatic   #34; //Field iniciado:Z
   5:   ifne    44
   8:   ldc_w   #35; //class reu/modulos/STDWDATES
   11:  dup
   12:  astore_3
   13:  monitorenter
   14:  getstatic   #34; //Field iniciado:Z
   17:  ifne    32
   20:  new #35; //class reu/modulos/STDWDATES
   23:  dup
   24:  invokespecial   #36; //Method "<init>":()V
   27:  pop
   28:  iconst_1
   29:  putstatic   #34; //Field iniciado:Z
   32:  aload_3
   33:  monitorexit
   34:  goto    44
   37:  astore  4
   39:  aload_3
   40:  monitorexit
   41:  aload   4
   43:  athrow
   44:  aconst_null
   45:  getstatic   #37; //Field AlmacenFechaCal:Ljava/util/HashMap;
   48:  aload_1
   49:  invokevirtual   #38; //Method java/util/HashMap.get:(Ljava/lang/Object;)Ljava/lang/Object;
   52:  if_acmpne   67
   55:  new #39; //class reu/exceptions/REUException
   58:  dup
   59:  bipush  58
   61:  bipush  17
   63:  invokespecial   #40; //Method reu/exceptions/REUException."<init>":(II)V
   66:  athrow
   67:  getstatic   #37; //Field AlmacenFechaCal:Ljava/util/HashMap;
   70:  aload_1
   71:  invokevirtual   #38; //Method java/util/HashMap.get:(Ljava/lang/Object;)Ljava/lang/Object;
   74:  checkcast   #41; //class reu/modulos/AlmancenFechas
   77:  astore_3
   78:  aload_3
   79:  invokevirtual   #42; //Method reu/modulos/AlmancenFechas.getFechaIni:()I
   82:  istore  4
   84:  invokestatic    #43; //Method java/util/Calendar.getInstance:()Ljava/util/Calendar;
   87:  astore  5
   89:  aload   5
   91:  aload_0
   92:  invokevirtual   #44; //Method java/util/Calendar.setTime:(Ljava/util/Date;)V
   95:  aload   5
   97:  iconst_1
   98:  invokevirtual   #45; //Method java/util/Calendar.get:(I)I
   101: istore  6
   103: iload   4
   105: iload   6
   107: if_icmple   112
   110: iconst_0
   111: istore_2
   112: iload_2
   113: ireturn
  Exception table:
   from   to  target type
    14    34    37   any
    37    41    37   any
  Exceptions: 
   throws reu.exceptions.REUException

I guess clue is ireturn expression in 113. According to oracle documentation for ireturn, it returns an int.

In this Casting conversions to primitive types, looks like a conversion from int to boolean, unlike C/C++, is not allowed.

How is that possible? Is there an implicit cast?

Thanks.

like image 267
Albert Avatar asked Feb 11 '23 21:02

Albert


2 Answers

The JVM uses integers to represent booleans. From the JVM Specification §2.3.4:

2.3.4. The boolean Type

Although the Java Virtual Machine defines a boolean type, it only provides very limited support for it. There are no Java Virtual Machine instructions solely dedicated to operations on boolean values. Instead, expressions in the Java programming language that operate on boolean values are compiled to use values of the Java Virtual Machine int data type.

You can check this out your self:

$ cat Test.java
class Test {
    boolean m() {
        return true;    <------------
    }
}
$ javac Test.java 
$ javap -c Test
Compiled from "Test.java"
class Test {
  [...]     

  boolean m();
    Code:
       0: iconst_1      
       1: ireturn        <------------
}
like image 64
aioobe Avatar answered Feb 13 '23 21:02

aioobe


The JVM represents booleans as ints: true is represented by 1 and false by 0. That's why the compiled code uses integers.

In other words, if you write that method and use booleans as follows (which probably what the original source was):

private static boolean checkMe(Date paramDate, String paramString)
       throws REUException {
   boolean i = true;
   int j, k;

    // unrelated stuff

    if (j > k)
        i = false;
    return i;
}

then the generated bytecode would contain ireturn at the end.

like image 30
M A Avatar answered Feb 13 '23 22:02

M A