java - online - jadx
Asignación extraña, TextView to Bundle, después de descompilar, ¿por qué? (2)
El código smali que proporcionaste parece correcto. Ejecutar la aplicación también funciona con el código fuente original. Sin embargo, el código proporcionado por jd-gui ni siquiera compila .
Tengo curiosidad y descompuse su aplicación con dex2jar. Subí el MainActivity.class resultante a este sitio web .
La parte interesante: algunos descompiladores ( Procyon y Fernflower ) generaron el código correcto y Fernflower variables separadas tanto para el paquete como para el TextView. Sin embargo, JAD y CFR cometieron el mismo error que jd-gui. Ambos usaron la variable Bundle para el TextView.
Parece que puedes culpar a jd-gui por el error. Lamentablemente, no puedo decir por qué ocurre.Creé una aplicación simple, una aplicación de contador, que al presionar un botón incrementa un número entero por uno y actualiza una vista de texto. El código se puede ver a continuación:
public class MainActivity extends Activity {
public static int count = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView textView = (TextView) findViewById(R.id.count);
textView.setText(Integer.toString(count));
final Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
count++;
textView.setText(Integer.toString(count));
}
});
}
...
}
Después de descompilar la misma aplicación con dex2jar y jd-gui, recibí el siguiente código:
public class MainActivity extends Activity {
public static int count = 0;
protected void onCreate(final Bundle paramBundle) {
super.onCreate(paramBundle);
setContentView(2130903040);
paramBundle = (TextView)findViewById(2131296257);
paramBundle.setText(Integer.toString(count));
((Button)findViewById(2131296256)).setOnClickListener(new View.OnClickListener() {
public void onClick(View paramAnonymousView) {
MainActivity.count += 1;
paramBundle.setText(Integer.toString(MainActivity.count));
}
});
}
...
}
En la siguiente línea:
paramBundle = (TextView)findViewById(2131296257);
paramBundle.setText(Integer.toString(count));
¿Cómo es posible que el sistema configure la vista de texto en paramBundle? ¿Y por qué sucede esto? paramBundle es de tipo Bundle y TextView no es una subclase de Bundle, aún más Bundle es definitivo según la versión descompilada. ¿Algo fue mal al descompilar? ¿Es incorrecta la información del descompilador o por qué obtenemos este resultado?
Editar:
# virtual methods
.method protected onCreate(Landroid/os/Bundle;)V
.locals 3
.param p1, "savedInstanceState" # Landroid/os/Bundle;
.prologue
.line 17
invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
.line 18
const/high16 v2, 0x7f030000
invoke-virtual {p0, v2}, Lcom/example/rawa/helloworld/MainActivity;->setContentView(I)V
.line 20
const v2, 0x7f090001
invoke-virtual {p0, v2}, Lcom/example/rawa/helloworld/MainActivity;->findViewById(I)Landroid/view/View;
move-result-object v1
check-cast v1, Landroid/widget/TextView;
.line 21
.local v1, "textView":Landroid/widget/TextView;
sget v2, Lcom/example/rawa/helloworld/MainActivity;->count:I
invoke-static {v2}, Ljava/lang/Integer;->toString(I)Ljava/lang/String;
move-result-object v2
invoke-virtual {v1, v2}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V
.line 22
const/high16 v2, 0x7f090000
invoke-virtual {p0, v2}, Lcom/example/rawa/helloworld/MainActivity;->findViewById(I)Landroid/view/View;
move-result-object v0
check-cast v0, Landroid/widget/Button;
.line 23
.local v0, "button":Landroid/widget/Button;
new-instance v2, Lcom/example/rawa/helloworld/MainActivity$1;
invoke-direct {v2, p0, v1}, Lcom/example/rawa/helloworld/MainActivity$1;-><init>(Lcom/example/rawa/helloworld/MainActivity;Landroid/widget/TextView;)V
invoke-virtual {v0, v2}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V
.line 30
return-void
.end method
Definitivamente no soy un experto en smali, solo un novato. Pero descodifiqué la aplicación usando apktool y recibí el código smali anterior. A mi entender, la instancia guardada (paramBundle) se carga en p1 (= v3) y se usa en onCreate, y no se usa de ninguna manera en la línea 20 o 21. Para mí, ¿esto apunta a un error de desconexión? Tenga en cuenta que apktool permite volver a crear la aplicación y, por lo tanto, no se pueden perder datos al descompilar.
La causa es que el tipo de variables locales ha cambiado, pero algunos decompiladores no lo manejan correctamente.
Aquí está su código onCreate
descompilado con dex2jar + javap :
protected void onCreate(android.os.Bundle);
Code:
0: aload_0
1: aload_1
2: invokespecial #20 // Method android/app/Activity.onCreate:(Landroid/os/Bundle;)V
5: aload_0
6: ldc #21 // int 2130903040
8: invokevirtual #25 // Method setContentView:(I)V
11: aload_0
12: ldc #26 // int 2131230720
14: invokevirtual #30 // Method findViewById:(I)Landroid/view/View;
17: checkcast #32 // class android/widget/TextView
20: astore_1
21: aload_1
22: getstatic #12 // Field count:I
25: invokestatic #38 // Method java/lang/Integer.toString:(I)Ljava/lang/String;
28: invokevirtual #42 // Method android/widget/TextView.setText:(Ljava/lang/CharSequence;)V
31: aload_0
32: ldc #43 // int 2131230721
34: invokevirtual #30 // Method findViewById:(I)Landroid/view/View;
37: checkcast #45 // class android/widget/Button
40: new #6 // class com/example/test/MainActivity$1
43: dup
44: aload_0
45: aload_1
46: invokespecial #48 // Method com/example/test/MainActivity$1."<init>":(Lcom/example/test/MainActivity;Landroid/widget/TextView;)V
49: invokevirtual #52 // Method android/widget/Button.setOnClickListener:(Landroid/view/View$OnClickListener;)V
52: return
Aquí aload_0
es una variable local para el objeto MainActivity, y aload_1
es una variable local para el objeto Bundle. La fuente del problema se produjo en el código # 20, cuando almacena la referencia del objeto TextView recién recuperado en la variable local 1 ( astore_1
), que estaba almacenando previamente el objeto del paquete.
Esto se hace ya que el objeto Bundle no se usa para el resto del método, por lo tanto, es más eficiente reutilizar su variable local en lugar de una nueva variable. Sin embargo, también significa que los descompiladores deben trabajar más para producir el código Java correcto.