我是靠谱客的博主 落后奇迹,这篇文章主要介绍Java Process:另一个程序正在使用此文件,进程无法访问,现在分享给大家,希望可以做个参考。

最近处理奇怪的问题时,犯了个低级错误,浪费了不少时间,甚至都看了 jdk 底层的 c 代码。

下面这段测试代码是在 Windows 环境运行的(Mac和linux换成 /bin/sh,-c 后没有问题),你能发现错误在哪里吗?

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Test public void test() throws Exception { String fileName = "out.log"; File file = new File(fileName); Process process = new ProcessBuilder(getCommands(fileName)).redirectOutput(file).start(); if(process.isAlive()) { process.waitFor(); } BufferedReader readStderr = new BufferedReader(new InputStreamReader(process.getErrorStream(), "gbk")); String line; while((line = readStderr.readLine()) != null) { System.err.println(line); } readStderr.close(); } public List<String> getCommands(String fileName) { String os = System.getProperty("os.name"); if (os.toLowerCase().startsWith("win")) { return Arrays.asList("cmd", "/c", "echo", "hello world", ">", fileName); } else { return Arrays.asList("/bin/sh", "-c", "echo", "hello world", ">", fileName); } }

Windows环境执行会提示错误 另一个程序正在使用此文件,进程无法访问,错误已经很直接了,但是由于在 Mac 和 Linux 环境没有问题,因此觉得类似的代码在 Windows 上也不存在问题。

debug过程中,修改 getCommands 中的 fileName 时也能成功,有时候修改就不能成功,有时候文件名短的时候能经常性的成功,偶尔会有长文件名的时候也能成功。

错误也很明显了吧?

仍然在迷糊中…

这里新建的文件名,为什么会被占用呢?Windows为什么不把被占用的文件名提示出来?

想看看C代码部分能不能提供有效的信息…

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
JNIEXPORT jlong JNICALL Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored, jstring cmd, jstring envBlock, jstring dir, jlongArray stdHandles, jboolean redirectErrorStream) { jlong ret = 0; if (cmd != NULL && stdHandles != NULL) { const jchar *pcmd = (*env)->GetStringChars(env, cmd, NULL); if (pcmd != NULL) { const jchar *penvBlock = (envBlock != NULL) ? (*env)->GetStringChars(env, envBlock, NULL) : NULL; if (!(*env)->ExceptionCheck(env)) { const jchar *pdir = (dir != NULL) ? (*env)->GetStringChars(env, dir, NULL) : NULL; if (!(*env)->ExceptionCheck(env)) { jlong *handles = (*env)->GetLongArrayElements(env, stdHandles, NULL); if (handles != NULL) { ret = processCreate( env, pcmd, penvBlock, pdir, handles, redirectErrorStream); (*env)->ReleaseLongArrayElements(env, stdHandles, handles, 0); } if (pdir != NULL) (*env)->ReleaseStringChars(env, dir, pdir); } if (penvBlock != NULL) (*env)->ReleaseStringChars(env, envBlock, penvBlock); } (*env)->ReleaseStringChars(env, cmd, pcmd); } } return ret; }

太长了…跳过…

由于代码不是我写的,所以处理过程中,没有仔细的看过完整的 Process 创建过程,有一瞬间,突然看到了问题的关键:

复制代码
1
2
3
4
redirectOutput(file) //和 ">", fileName

上面这个方法已经把输出重定向到 file 了,new File(fileName) 时和命令当前执行的路径是一样的,通过 > fileName 时也是重定向到 fileName 中,所以 另一个程序正在使用此文件,进程无法访问,另一个程序竟然就是自己。

将上面两种方式随便去掉哪一个都可以正常运行。

你在看本文的过程中,有没有更早的发现问题呢?

当 Windows 提示你的操作遇到 “另一个程序正在使用此文件,进程无法访问” 时,这个文件大概率就是你操作的文件,如果找不到其他被使用的地方,可能就是你自己重复使用了同一个文件。

最后

以上就是落后奇迹最近收集整理的关于Java Process:另一个程序正在使用此文件,进程无法访问的全部内容,更多相关Java内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(60)

评论列表共有 0 条评论

立即
投稿
返回
顶部