Descompilación para-cada bucle

csirmazbendeguz:

Descompilación el archivo .class de los siguientes fines de cada bucle produce resultados interesantes.

Fuente - Main.java:

public class Main {
    public static void main(String[] args) {
        String[] names = new String[3];
        int var3 = 3;

        for (String name : names) {
            System.out.println(name);
        }
    }
}

Resultado - Main.class:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

public class Main {
    public Main() {
    }

    public static void main(String[] args) {
        String[] names = new String[3];
        int var3 = true;
        String[] var3 = names;
        int var4 = names.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            String name = var3[var5];
            System.out.println(name);
        }

    }
}

El archivo se decompiled con IntelliJ IDEA.

  • Por lo que fue trueasignado a la no utilizada int?
  • ¿Por qué el var3redeclarada variable?

¿Es esto un error en nombre de la decompilador?

Holger:

En el nivel de código de bytes, no hay declaraciones formales de las variables locales, al menos no de la manera conocida a partir del código fuente. Un método tiene una declaración del número máximo de variables locales existentes, al mismo tiempo o “slots” para reservar para ellos. Una variable local entra en la vida cuando se asigna un valor real a la misma (por el índice de “ranura”) y existe al menos en la última lectura de ese valor.

Con estas operaciones, es imposible reconocer cuando extremos de alcance de una variable o si dos variables con alcances disjuntos comparten una ranura (en comparación con múltiples asignaciones a la misma variable). Bueno, si tienen tipos completamente incompatibles, sus asignaciones dar una pista.

Para ayudar a la depuración, existe un atributo código opcional que proporciona consejos acerca de las variables locales declaradas y su alcance, pero esto no es necesario que sea completa y no afectará a la forma en la JVM ejecutará el código de bytes. Pero aquí, parece que el atributo estaba presente y ha sido utilizado por el decompilador.

Cuando puedo compilar el código de ejemplo, con javac -g, consigo

public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
  stack=2, locals=7, args_size=1
     0: iconst_3
     1: anewarray     #2        // class java/lang/String
     4: astore_1
     5: iconst_3
     6: istore_2
     7: aload_1
     8: astore_3
     9: aload_3
    10: arraylength
    11: istore        4
    13: iconst_0
    14: istore        5
    16: iload         5
    18: iload         4
    20: if_icmpge     43
    23: aload_3
    24: iload         5
    26: aaload
    27: astore        6
    29: getstatic     #3        // Field java/lang/System.out:Ljava/io/PrintStream;
    32: aload         6
    34: invokevirtual #4        // Method java/io/PrintStream.println:(Ljava/lang/String;)V
    37: iinc          5, 1
    40: goto          16
    43: return
  LocalVariableTable:
    Start  Length  Slot  Name   Signature
       29       8     6  name   Ljava/lang/String;
        0      44     0  args   [Ljava/lang/String;
        5      39     1 names   [Ljava/lang/String;
        7      37     2  var3   I

Las variables declaradas args(el parámetro método), names, var3, y namefueron asignados a los índices variables 0, 1, 2, y 6, en ese orden.

Hay variables sintéticas sin una declaración,

  • en el índice 3para contener una referencia a la matriz el bucle se iterar sobre
  • en el índice 4para mantener la longitud de la matriz
  • en el índice 5para mantener la intvariable de índice que logrará incrementado en el bucle

Parece, la decompilador tiene una simple estrategia para hacer frente a las variables que no aparecen en el LocalVariableTable. Se genera un nombre que consiste en el prefijo "var"y el índice dentro del marco de pila. Por lo tanto, genera los nombres var3, var4y var5para las variables de síntesis descrito anteriormente y no le importaba que se produjo un enfrentamiento nombre entre estos nombres generados y los nombres declarados explícitamente, es decir var3.

Ahora, no está claro por qué el decompilador genera una asignación de trueuna intvariable, pero es muy útil saber que no hay dedicados booleaninstrucciones de procesamiento en el código de bytes de Java, sino más bien booleanlos valores se procesan del mismo modo que intlos valores. Se requiere información meta apropiada, como declaraciones de variables, para entender que los valores deben conseguir interpretado como booleanvalores. Tal vez, el nombre choque descrita anteriormente dirigió el decompilador confundir los tipos de variables después, tener en cuenta, finalmente, el tipo de valor de no ser una inty caer de nuevo a tratarlo como booleana continuación. Pero eso es sólo una conjetura; podría haber un fallo del todo ajeno también.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=189400&siteId=1
Recomendado
Clasificación