非主线程读取 /proc/self/exe 时出现 Android 权限被拒绝

5
我正在尝试获取/proc/self/exe的规范路径。当我在主线程上执行此操作时,它可以正常工作,但当我在另一个线程上执行时,它会因IOException:"Permission denied"而崩溃。
                   DBG  E  Thread: main
                        E  Path: /system/bin/app_process32
                        E  Thread: Thread-21656
            System.err  W  java.io.IOException: Permission denied
                        W      at java.io.File.canonicalizePath(Native Method)
                        W      at java.io.File.getCanonicalPath(File.java:414)
                        W      at java.io.File.getCanonicalFile(File.java:428)
                        W      at com.quanturium.testbugprocselfexe.MyActivity.getPathOfExecutable(MyActivity.java:36)
                        W      at com.quanturium.testbugprocselfexe.MyActivity.access$000(MyActivity.java:12)
                        W      at com.quanturium.testbugprocselfexe.MyActivity$1.run(MyActivity.java:26)
                        W      at java.lang.Thread.run(Thread.java:818)

代码:

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

    getPathOfExecutable(); // Works as expected

    new Thread(new Runnable() {
        @Override
        public void run ()
        {
            getPathOfExecutable(); // Trigger the IOException: Permission denied
        }
    }).start();
}

private void getPathOfExecutable()
{
    try
    {
        Log.e("DBG", "Thread: " + Thread.currentThread().getName());
        Log.e("DBG", "Path: " + new File("/proc/self/exe").getCanonicalFile().getPath());
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
}

当build.gradle文件中的debuggable被配置为false时,才会发生此错误。

试用代码:https://github.com/quanturium/TestBugProcSelfExe

这是一个bug还是预期行为?如何解决获取当前可执行文件路径的问题?


每当我遇到权限问题时,尽管权限不同,但logcat在异常被打印出来之前准确指出了缺失的哪个权限。那么,在异常之前的10行左右有什么内容? - Corey Ogburn
不,这就是整个错误。 - Quanturium
可能这就是整个错误,但当我在读取警报名称时遇到问题时,有一个不同的日志条目与错误分开,告诉我需要READ_EXTERNAL_STORAGE权限。 - Corey Ogburn
相信我,这就是所有需要看到的。 - Quanturium
你有取得任何进展吗?这个问题引起了我的好奇心。 - MeetTitan
显示剩余3条评论
2个回答

1

代码会阻塞吗?如果不会,那么在主线程中运行它不应该有任何影响。但是,您可以在另一个线程中这样做:

Context.runOnUiThread(new Runnable() {
    getPathOfExecutable();
});

这是我所能想到的最干净的解决方案,除了编辑文件权限(你无法获取它的路径而不在主线程上运行代码),因为你在/proc/self/exe上有读写权限。
这非常奇怪,我仍在研究Android上不同线程之间的权限差异。
如果你可以在主线程中让它工作,那么我的建议是在主线程中完成,并不要过于关注优化,因为性能在不同线程上没有区别。

这段代码确实在主线程上运行(这就是为什么我问它是否阻塞)。我不确定为什么不同的线程具有不同的权限,所以这可能是最好的方法。 - MeetTitan
lrwxrwxrwx u0_a416 u0_a416 2015-02-20 16:36 exe -> /system/bin/toolbox - Quanturium
/proc/self/exe 的权限看起来不错。请注意,/proc/self/exe 是指向 /system/bin/toolbox 的链接。ls -al /system/bin/toolbox 的输出是什么? - MeetTitan
不,只能在主线程中使用。反正我也不太关心工具箱。我想使用/proc/self/exe来检测我的可执行文件路径,这是一个用C编写的库(对于问题来说并不重要...) - Quanturium
抱歉,我误解了。你可以使用readlink /proc/self/exe,但这似乎不太优雅。你不能直接使用/proc/self/exe作为可执行文件的路径吗? - MeetTitan
显示剩余5条评论

0
有什么方法可以获取当前可执行文件的路径?
由于每个Android应用程序都是从Zygote分叉而来的,Zygote是在系统引导时由/system/bin/app_process创建的第一个Java虚拟机进程。
如果您尝试从Android应用程序中读取/proc/self/exe,则实际可执行文件将是/system/bin/app_process。即使在应用程序的主线程之外读取此文件,结果也是相同的,并且理论上不会出现权限错误。
你提出的问题有点奇怪,我已经在Android 2.3.3上测试了以下代码,运行良好。
new Thread() {

    /* (non-Javadoc)
     * @see java.lang.Thread#run()
     */
    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
        try {
            Log.d(TAG, new File("/proc/self/exe").getCanonicalFile().getPath());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}.start();

我想在JNI库中使用本地C将其作为命令行读取。在Java中出现了相同的错误(IO权限被拒绝),因此我决定将Java用于简化。是的,它可以在Android 2.3上运行。有人建议SE Linux可能是原因。 - Quanturium

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接