簡體   English   中英

為什么控制台 android java 應用程序在沒有 ODEX 文件的情況下不能工作,同時 GUI 應用程序運行良好?

[英]Why doesn't console android java application work without ODEX file, at the same time when GUI application works good?

我為 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/ ”目錄並從root創建了一個新目錄,訪問標志更改為771(相同的訪問標志“ /data/dalvik-cache/ ”目錄具有) . 因此,如果 Dalvik VM 不是從 root 啟動的,則無法寫入“ /data/local/tmp/dalvik-cache/ ”。

所以在所有這些步驟之后:

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 應用程序。

如果我在第一次啟動“ my_app-1.apk ”之前刪除 odex 文件“ /data/dalvik-cache/data@app@com.example.my_app-1.apk@classes.dex ”,“ my_app-1.apk "之后就不行了。 這是Android日志(我稍微修改了dalvik):

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 作弊,那就太好了。

始終需要 odex 文件。 classes.dex必須從 zip 文件中提取,必要時進行字節交換,並執行一些基本的結構驗證。 對於 GUI 應用程序,包管理器會在必要時自動重新創建它; PM 具有更新/data/dalvik-cache的必要權限。

該過程的完整解釋可以在 Dalvik 源 ( dalvik/docs/dexopt.html ) 中找到。 (其中一些有點過時,但大部分是正確的。)

順便說一句,在您的創建步驟中,如果您告訴dx創建foo.zipfoo.jar而不是foo.dex ,它將自動為您壓縮輸出文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM