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.apk
my_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チートの原因となっているサービス/アプリケーション/などを説明してくれると私が言っているのは正しいのでしょうか。