Android DexClassLoader 错误,“优化数据目录..不属于当前用户”

2023-11-30

我正在尝试生成一个简单的 Android 应用程序,可以在运行时从 SD 卡加载 DEX 文件。

该应用程序有两个活动。第一个活动是一个带有按钮的简单屏幕。当按下按钮时,将启动第二个活动,从而调用 loadDex() 方法。 loadDex() 方法尝试在 SD 卡上找到 jar 文件并将其加载到当前应用程序中。

这是我的第一个活动的代码:

package poc.example.del.customclass;

import android.content.Intent;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;


public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    public void launchLoadClass(View view) {
        Intent intent = new Intent(MainActivity.this, LoadClass.class);
        startActivity(intent);
    }
}

这是我的第二个活动的代码(加载 DEX 文件的活动):

package poc.example.del.customclass;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import dalvik.system.DexClassLoader;


public class LoadClass extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_load_class);
        loadDex();
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_load_class, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    public void loadDex() {
        String dexFile = "/sdcard/output.jar";
        File jarFile = new File(dexFile);
        if (jarFile.exists()) {
            // Toast.makeText(getApplicationContext(), "It Worked!", Toast.LENGTH_LONG).show();
            DexClassLoader cl = new DexClassLoader (jarFile.toString (), "/data/test", null, ClassLoader.getSystemClassLoader());

        }
    }
}

调用 DexClassLoader 构造函数时会出现问题。在日志中可以发现如下错误:

03-25 10:15:48.441    1934-1934/poc.example.del.customclass E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.RuntimeException: Unable to start activity ComponentInfo{poc.example.del.customclass/poc.example.del.customclass.LoadClass}: java.lang.IllegalArgumentException: Optimized data directory /data/test is not owned by the current user. Shared storage cannot protect your application from code injection attacks.
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
            at android.app.ActivityThread.access$600(ActivityThread.java:141)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5039)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.IllegalArgumentException: Optimized data directory /data/test is not owned by the current user. Shared storage cannot protect your application from code injection attacks.
            at dalvik.system.DexFile.<init>(DexFile.java:100)
            at dalvik.system.DexFile.loadDex(DexFile.java:149)
            at dalvik.system.DexPathList.loadDexFile(DexPathList.java:261)
            at dalvik.system.DexPathList.makeDexElements(DexPathList.java:229)
            at dalvik.system.DexPathList.<init>(DexPathList.java:96)
            at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:56)
            at dalvik.system.DexClassLoader.<init>(DexClassLoader.java:57)
            at poc.example.del.customclass.LoadClass.loadDex(LoadClass.java:54)
            at poc.example.del.customclass.LoadClass.onCreate(LoadClass.java:23)
            at android.app.Activity.performCreate(Activity.java:5104)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
            at android.app.ActivityThread.access$600(ActivityThread.java:141)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5039)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
            at dalvik.system.NativeStart.main(Native Method)

这是日志中我认为代表问题的行:

java.lang.IllegalArgumentException: Optimized data directory /data/test is not owned by the current user. Shared storage cannot protect your application from code injection attacks.

任何帮助将不胜感激,因为我在网上找到的有关该问题的信息很少。我正在开发适用于 Android 4.2、Api 17 的应用程序。

提前致谢。


经过几天的学习各种教程后,我找到了答案。我想我会在这里发布解决方案,以防其他人遇到类似的问题。

出于安全原因,Android 不允许应用程序将文件加载到任何随机文件夹。相反,它应该加载到应用程序环境中。这是修改后的代码,使我能够继续该项目。显示的代码适用于“loadDex()”方法:

public void loadDex() {
    // Toast the show the method has been invoked correctly
    // Toast.makeText(getApplicationContext(), "loadDex() Method invoked", Toast.LENGTH_LONG).show();

    // name of the DEX file
    String dexFile = "/output.jar";

    // Get the path to the SD card
    File f = new File(Environment.getExternalStorageDirectory().toString() + dexFile);

    // optimized directory, the applciation and package directory
    final File optimizedDexOutputPath = getDir("outdex", 0);

    // DexClassLoader to get the file and write it to the optimised directory
    DexClassLoader classLoader = new DexClassLoader(f.getAbsolutePath(),
    optimizedDexOutputPath.getAbsolutePath(),null, getClassLoader());

    // The classpath is created for the new class
    String completeClassName = "poc.example.del.mylibrary.name";
    String methodToInvoke = "display";

    try {
        Class<?> myClass = classLoader.loadClass(completeClassName);
        Object obj = (Object)myClass.newInstance();
        Method m = myClass.getMethod(methodToInvoke);
        String s = ""+m.invoke(obj);
        makeToast(s);
    }
    catch (Exception e) {
        e.printStackTrace();
        makeToast("Something went wrong!");
    }


}

解决问题的具体代码行是:

// DexClassLoader to get the file and write it to the optimized directory
DexClassLoader classLoader = new DexClassLoader(f.getAbsolutePath(),
optimizedDexOutputPath.getAbsolutePath(),null, getClassLoader());

如您所见,optimizedDexOutputPath,getAbsolutePath() 方法返回应用程序可用于写入文件的目录。

希望这可以帮助其他遇到类似问题的人!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android DexClassLoader 错误,“优化数据目录..不属于当前用户” 的相关文章

随机推荐

  • wxpython——线程和窗口事件

    我有一个 wxPython 应用程序 http www OpenSTV org 使用多轮方法计算选票 我想做两件事 1 对于大量选票 这可能有点慢 所以我想向用户显示一个进度对话框 这样他就不会认为应用程序被冻结 2 我想允许用户手动打破平
  • 在 google go 中使用 olivere/elastic 更新 ElasticSearch 中的记录

    我正在使用 go 在弹性搜索中插入一条记录 如下所示 https github com olivere elastic现在 如果我必须部分更新它 假设只有一个条目 如 名称 那么我想使用 UPDATE API 我找不到任何描述如何在 oil
  • JSF RichTable 合并标题中的行/列

    我想做的是做这个布局RichTable在其标题中有 3 列 3 5 1 2 4 6 我已经习惯了this 8 2 完成任务的资源 富脸4 0 0 但相反 我最终得到了没有任何合并的普通表行 您能解释一下吗 Update 关于来自的答案瓦西尔
  • 多个组件 - 性能损失?

    我有一个清单System IO Ports SerialPort一个程序集中的对象 并且我计划处理来自另一个程序集的 Data Receieved 事件 我想知道这是否会以某种方式影响性能 会吗 恐怕我不太清楚 CLR 如何管理程序集 谢谢
  • 从 VS 05 中的资源设置应用程序图标

    我知道我可以将图标添加到项目的 Resources resx 文件中 然后从代码中引用该图标 如何从资源中设置整个EXE的图标 我所看到的只是浏览另一个文件的地方 我想使用我的资源中的当前图标文件 而不必在我的项目中拥有重复的文件 than
  • 如何将两个独立但相似的代码库合并到一个 SVN 代表中?

    I have www example com 上的 var www cool codebase 并且我有 www example net 上的 var www cool codebase 代码库适用于在不同服务器上运行的同一 Web 应用程
  • 将 nil 排序到可选字符串数组的末尾

    如果我有一个可选字符串数组 并且我想以 nils 开头按升序对它进行排序 我可以在一行中轻松完成 b nil a sorted 0 lt 1 nil a b 但似乎没有任何类似简单的解决方案可以将 nil 排序到end数组的 使用大多数其他
  • 是否有 Visual Studio 插件的配置类型文件?

    创建 Visual Studio 加载项时 如何利用该加载项的 app config 如果我向项目添加一个并部署它 那么当加载项运行并且我以编程方式尝试通过 ConfigurationManager AppSettings 访问它时 它不会
  • xargs 在搜索中尊重通配符

    我有一个名为 file1 txt 的文件 dir1 dir2 dir3 我想使用 xargs 检查某些文件是否存在于文件系统中 如下所示 cat file1 txt xargs i ls projects analysis7 meta bw
  • IHttpContextAccessor.HttpContext.User.Identity 显示 CurrentUserService 服务中的所有 null 属性

    我正在尝试使用Jason Taylor 的简洁架构模板 这个模板使用 NSwag 自动创建 TypeScript 客户端 Angular 但我不需要创建 TS 客户端 所以我的主要目标是用 Razor Pages 替换它 我已经能够取得高分
  • Cocoa:每次方法调用都会中断?

    通常 在调试时 了解以什么顺序调用类的哪些方法对我来说很重要 天真的解决方案 到目前为止我一直在使用 是弹出一个NSLog在每个方法的顶部 但这是耗时的 重复的 丑陋的 并且如果我在调试后忘记删除日志 会让我的代码看起来很幼稚 一个更干净的
  • Toast 不从列表中选定的项目生成文本

    我在android中用列表视图制作了一个简单的应用程序 因为我想在选择一个项目时进行吐司 我已经尝试如下 但它不起作用 我的代码如下 main java package com example listview import java ut
  • ZF2 骨架应用程序抛出 500 错误

    当尝试使用以下命令部署骨架应用程序时 git clone git github com zendframework ZendSkeletonApplication git cd ZendSkeletonApplication php com
  • 将数组传递给 useEffect 依赖项列表

    每 5 秒长轮询会产生一些数据 我希望我的组件在每次数组的一项 或数组长度本身 发生变化时调度一个操作 在将数组作为依赖项传递给 useEffect 时 如何防止 useEffect 进入无限循环 但如果任何值发生变化 仍然设法调度一些操作
  • 运算符和方法之间的区别

    运算符和方法之间有本质区别吗 我看到的唯一区别是它们的调用方式 它们还有其他区别吗 例如在Python中连接 切片 索引被定义为运算符 而 指字符串 upper replace strip 等等都是方法 如果我正确理解问题 简而言之 一切都
  • Python pygame 未安装

    C Users matth gt pip3 安装 pygame 收集pygame 使用缓存的 pygame 2 1 2 tar gz 10 1 MB 准备元数据 setup py 错误 错误 子进程退出并出现错误 python setup
  • Javascript 和 RegEx:分割​​并保留分隔符

    我有一个正则表达式 它将把我的字符串分割成数组 一切工作正常 除了我想保留分隔符的一部分 这是我的正则表达式 a zA Z0 9 s 在 JavaScript 中 我正在做 var test paragraph split a zA Z0
  • 有没有办法使用 ServiceTask 在控制台应用程序中托管 Razor 页面?

    我正在尝试创建一个控制台应用程序来公开 JSON 服务 另外我想托管 html 和 js 页面来使用它们 我将 md 甚至 htm 文件放入 Views 文件夹中 但我无法访问它们 如果我添加一条路线 Add Test 其中 MyMarkd
  • 46 个 SQL 加载程序的控制文件

    我必须使用 SQL Loader for Oracle 加载 46 个表的数据 所有数据文件均为 CSV CSV 中的列顺序与表中的列顺序匹配 我需要为每个表创建一个控制文件 我批量生产这些文件的最佳方法是什么 我知道这是一个老问题 但它仍
  • Android DexClassLoader 错误,“优化数据目录..不属于当前用户”

    我正在尝试生成一个简单的 Android 应用程序 可以在运行时从 SD 卡加载 DEX 文件 该应用程序有两个活动 第一个活动是一个带有按钮的简单屏幕 当按下按钮时 将启动第二个活动 从而调用 loadDex 方法 loadDex 方法尝