studio online jadx descompilar decompile java android decompiling

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.