我为 Android 4.1.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)图形用户界面应用:
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);
}
}
它以标准方式构建。
每个应用程序都可以正常启动。我启动控制台程序的方式是在之前插入的 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 应用程序证明了这个理论。但控制台应用程序没有。
有人可以解释一下,为什么在没有 ODEX 文件的情况下控制台 android java 应用程序不能工作,同时 GUI 应用程序感觉很好?
更新:
我更彻底地测试了我的 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 一切正常。Android日志中也没有“ /data/app/com.example.my_app-1.apk
”文件读取。我想,Android 将 ODEX 放在 RAM 中的某个位置进行优化,然后在必要时设置一个指向它的指针。
所以,法登先生是对的,所有赞同他的人也是对的!:)
太好了,如果有人能回答我是否正确地说 Android 将应用程序留在 RAM 中进行优化,并向我解释是什么服务/应用程序/等...对这个 Android 作弊负责。