0

Android 4.1.2 用の 2 つの単純な Java プログラムを作成しました。

1) コンソール プログラム:

public class console_hello_world
{
    console_hello_world() {
        System.out.println("Init!");
    }
    protected static int method() {
        System.out.println("Method!");
        return 0;
    }
    public static void main(String[] args)
    {   console_hello_world variable=new console_hello_world();
        variable.method();
        System.out.println("Hello World!");
    }
}

このような方法で構築されました (ご覧のとおり、このスクリプトはこのプログラムも起動します)。

#!/bin/bash

DX="~/Programs/android-sdk-linux/build-tools/18.0.1/dx"
REMOTE_PATH=/data/local/tmp

CLASS_NAME="console_hello_world"
javac "${CLASS_NAME}.java"
${DX} --dex --output="classes.dex" "${CLASS_NAME}.class"
zip "${CLASS_NAME}.zip" "classes.dex"

ADB="~/Programs/android-sdk-linux/platform-tools/adb"
"${ADB}" push "${CLASS_NAME}.zip" $REMOTE_PATH/
"${ADB}" shell mkdir $REMOTE_PATH/dalvik-cache

"${ADB}" shell "logcat -c"
"${ADB}" shell ANDROID_DATA=$REMOTE_PATH dalvikvm -cp "$REMOTE_PATH/${CLASS_NAME}.zip" ${CLASS_NAME}
"${ADB}" shell "logcat -d" > out.log

2) GUI アプリケーション:

package com.example.my_app;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;

public class my_app_activity extends Activity
{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    /** Called when the user clicks the button */
    public void onButtonClickMethod(View view)
    {
        // do smth
        EditText editText = (EditText) findViewById(R.id.edit_message);
        String message = editText.getText().toString();
        message += " + something!\n";
        editText.setText(message);
    }
}

それは標準的な方法で構築されました。

各アプリ起動OK。コンソール プログラムの起動方法は、先ほど挿入した bash スクリプトにあります。

次に、各プログラムの ODEX ファイルを削除しました。

/data/local/tmp/dalvik-cache/data@local@tmp@console_hello_world.zip@classes.dex

/data/dalvik-cache/data@app@com.example.my_app-1.apk@classes.dex

(問題ありません - 私の GUI アプリケーション名は「my_app-1.apk」です)

コンソール プログラムについても、" " ディレクトリを削除/data/local/tmp/dalvik-cache/し、ルートから新しいディレクトリを作成しました。アクセス フラグは 771 に変更されました (アクセス フラグ " /data/dalvik-cache/" ディレクトリと同じです)。/data/local/tmp/dalvik-cache/そのため、ルートから起動されていない場合、Dalvik VM は「 」に書き込むことができません。

したがって、これらすべての手順の後:

1) GUI アプリケーションは問題なく動作します。Dalvik VM プロセスは「/data/dalvik-cache/」にアクセスできず、新しい ODEX ファイルが作成されていません。

2) コンソール アプリケーションが例外をスローします。

Dalvik VM unable to locate class 'console_hello_world'
java.lang.NoClassDefFoundError: console_hello_world
    at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ClassNotFoundException: console_hello_world
    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
    ... 1 more

それは私にとって驚くべきことです。

ODEXファイルはclasses.dexファイルの検証および最適化されたバージョンであり、アーカイブにあり、アプリケーションはそれなしで動作すると思ったからです。

私の GUI アプリケーションは、この理論を証明しています。しかし、コンソール アプリケーションはそうではありません。

誰かが私に説明してもらえますか?GUIアプリケーションが気持ちいいのに、コンソールAndroid JavaアプリケーションがODEXファイルなしで動作しないのはなぜですか?

アップデート:

GUI アプリケーションをより徹底的にテストしました。

初めて/data/dalvik-cache/data@app@com.example.my_app-1.apk@classes.dex" " を起動する前にodex ファイル " " を削除すると、" " はその後動作しなくなります。これがAndroidログです(dalvikを少し変更しました):my_app-1.apkmy_app-1.apk

W/ActivityThread( 4133): Application com.example.my_app can be debugged on port 8100...
I/dalvikvm( 4133): dvmJarFileOpen. fileName = /data/app/com.example.my_app-1.apk; odexOutputName = (null)
I/dalvikvm( 4133): dvmOpenCachedDexFile. fileName = /data/app/com.example.my_app-1.apk; cacheFileName = /data/dalvik-cache/data@app@com.example.my_app-1.apk@classes.dex
E/dalvikvm( 4133): Dex cache directory isn't writable: /data/dalvik-cache
I/dalvikvm( 4133): Unable to open or create cache for /data/app/com.example.my_app-1.apk (/data/dalvik-cache/data@app@com.example.my_app-1.apk@classes.dex)
D/AndroidRuntime( 4133): Shutting down VM

しかし、以前に my_app-1.apk を数回起動した後で ODEX ファイルを削除すると、my_app-1.apk ですべて問題ありません。また/data/app/com.example.my_app-1.apk、Android のログに " " ファイルの読み込みはありません。Android は最適化のために ODEX を RAM のどこかに配置し、必要なときにポインタを設定するだけだと思います。

つまり、ファデン氏は正しかったし、彼に同意した人もすべて正しかった! :)

Androidは最適化のためにアプリケーションをRAMに残し、このAndroidチートの原因となっているサービス/アプリケーション/などを説明してくれると私が言っているのは正しいのでしょうか。

4

1 に答える 1

2

odex ファイルは常に必要です。を zip ファイルから抽出し、classes.dex必要に応じてバイト スワップし、基本的な構造検証を実行する必要があります。GUI アプリの場合、パッケージ マネージャーは必要に応じて自動的に再作成します。PM は、更新に必要な権限を持ってい/data/dalvik-cacheます。

プロセスの完全な説明は、Dalvik ソース ( dalvik/docs/dexopt.html ) にあります。(少し古いものもありますが、ほぼ正しいです。)

ところで、作成ステップで、作成するか、代わりにdx作成するように指示すると、出力ファイルが自動的に圧縮されます。foo.zipfoo.jarfoo.dex

于 2013-10-30T15:05:45.043 に答える