You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows环境下Android(Kotlin)测试报错:'posix:permissions'不支持作为初始属性

Windows运行Android测试触发POSIX权限错误的修复方案

问题概述

在Windows上跑Android应用测试时遇到了'posix:permissions' not supported as initial attribute错误,疑问是不是必须用Mac/Linux才能跑部分Android测试——明确自己没直接调用POSIX接口,是测试库内部触发的问题。

完整报错栈

'posix:permissions' not supported as initial attribute
java.lang.UnsupportedOperationException: 'posix:permissions' not supported as initial attribute    
at java.base/sun.nio.fs.WindowsSecurityDescriptor.fromAttribute(WindowsSecurityDescriptor.java:358)
at java.base/sun.nio.fs.WindowsFileSystemProvider.createDirectory(WindowsFileSystemProvider.java:509)
at java.base/java.nio.file.Files.createDirectory(Files.java:700)
at java.base/java.nio.file.TempFileHelper.create(TempFileHelper.java:134)
at java.base/java.nio.file.TempFileHelper.createTempDirectory(TempFileHelper.java:171)
at java.base/java.nio.file.Files.createTempDirectory(Files.java:976)
at com.google.common.io.TempFileCreator$JavaNioCreator.createTempDir(TempFileCreator.java:102)
at com.google.common.io.Files.createTempDir(Files.java:439)
at org.robolectric.internal.dependency.MavenArtifactFetcher.fetchArtifact(MavenArtifactFetcher.java:70)
at org.robolectric.internal.dependency.MavenDependencyResolver.lambda$getLocalArtifactUrls$0(MavenDependencyResolver.java:93)
at org.robolectric.internal.dependency.MavenDependencyResolver.whileLocked(MavenDependencyResolver.java:113)
at org.robolectric.internal.dependency.MavenDependencyResolver.getLocalArtifactUrls(MavenDependencyResolver.java:88)
at org.robolectric.internal.dependency.MavenDependencyResolver.getLocalArtifactUrls(MavenDependencyResolver.java:78)
at org.robolectric.internal.dependency.MavenDependencyResolver.getLocalArtifactUrl(MavenDependencyResolver.java:129)
at org.robolectric.plugins.LegacyDependencyResolver.getLocalArtifactUrl(LegacyDependencyResolver.java:89)
at org.robolectric.plugins.DefaultSdkProvider$DefaultSdk.getJarPath(DefaultSdkProvider.java:148)
at org.robolectric.internal.AndroidSandbox$SdkSandboxClassLoader.<init>(AndroidSandbox.java:128)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at org.robolectric.util.inject.Injector.inject(Injector.java:250)
at org.robolectric.util.inject.Injector.lambda$memoized$1(Injector.java:232)
at org.robolectric.util.inject.Injector$MemoizingProvider.get(Injector.java:498)
at org.robolectric.util.inject.Injector.getInstanceInternal(Injector.java:224)
at org.robolectric.util.inject.Injector.resolveDependencies(Injector.java:296)
at org.robolectric.util.inject.Injector.inject(Injector.java:248)
at org.robolectric.util.inject.Injector.lambda$memoized$1(Injector.java:232)
at org.robolectric.util.inject.Injector$MemoizingProvider.get(Injector.java:498)
at org.robolectric.util.inject.Injector.getInstanceInternal(Injector.java:224)
at org.robolectric.util.inject.Injector.getInstance(Injector.java:208)
at org.robolectric.util.inject.Injector.access$700(Injector.java:96)
at org.robolectric.util.inject.Injector$ScopeBuilderProvider.create(Injector.java:564)
at org.robolectric.util.inject.Injector$ScopeBuilderProvider.lambda$get$0(Injector.java:547)
at jdk.proxy3/jdk.proxy3.$Proxy24.build(Unknown Source)
at org.robolectric.internal.SandboxManager.getAndroidSandbox(SandboxManager.java:62)
at org.robolectric.RobolectricTestRunner.getSandbox(RobolectricTestRunner.java:299)
at org.robolectric.RobolectricTestRunner.getSandbox(RobolectricTestRunner.java:66)
at org.robolectric.internal.SandboxTestRunner$2.evaluate(SandboxTestRunner.java:244)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.robolectric.internal.SandboxTestRunner$1.evaluate(SandboxTestRunner.java:101)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at androidx.test.ext.junit.runners.AndroidJUnit4.run(AndroidJUnit4.java:162)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:108)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:40)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:60)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:52)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at jdk.proxy1/jdk.proxy1.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)

问题根源

不是Windows不能跑Android测试,纯粹是Robolectric依赖的旧版Guava库在创建临时目录时硬编码了POSIX权限属性,而Windows文件系统不支持POSIX权限模型,直接触发了不支持操作的异常。从栈信息能看到,错误始于Guava的Files.createTempDir()方法,它传递了Windows无法处理的权限参数。

修复方案

1. 升级Guava到兼容版本

Guava 30.1.1-jre及以上版本已经修复了这个跨平台问题,会自动根据操作系统选择正确的临时目录创建逻辑,不再强制设置POSIX权限。直接升级项目里的Guava依赖就能解决。

2. 强制Robolectric使用系统默认临时目录

如果没法升级Guava,就给Robolectric指定系统默认的临时目录,避免它自行创建带POSIX权限的目录:

  • 在build.gradle里添加:
test {
    systemProperty "robolectric.tempdir", System.getProperty("java.io.tmpdir")
}
  • 或者在测试类里加静态代码块:
static {
    System.setProperty("robolectric.tempdir", System.getProperty("java.io.tmpdir"));
}

3. 升级Robolectric版本

Robolectric 4.9及以上版本针对Windows做了兼容性优化,减少了对POSIX相关API的依赖,升级后也能避免这类问题。

总结

Windows完全可以运行Android测试,这个问题只是依赖库的跨平台Bug,不用切换到Mac/Linux,按上面的方案调整就能解决。

内容的提问来源于stack exchange,提问作者akrelj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 01:01:57