【问题标题】:IllegalAccessError: Method is inaccessible to classIllegalAccessError:类无法访问方法
【发布时间】:2025-11-22 10:10:01
【问题描述】:

我有一个非常奇怪的错误,因为它仅在从生成的.apk 安装应用程序后发生。当我尝试通过 IDE 运行应用程序时,它运行良好。

java.lang.IllegalAccessError: Method 'int <package>.BaseActivity$Companion.getANIMATION_SLIDE_FROM_RIGHT()' is inaccessible to class '<package>.MyActivity' (declaration of '<package>.MyActivity' appears in /data/app/<package>-mg7eYmJ8hX5WvkNWNZWMVg==/base.apk!classes3.dex)

如您所见,有一个名为 BaseActivity 的类,如下所示:

open class BaseActivity : AppCompatActivity() {

    companion object {
        @JvmStatic
        protected val ANIMATION_DEFAULT = 0
        @JvmStatic
        protected val ANIMATION_SLIDE_FROM_RIGHT = 1
        @JvmStatic
        protected val ANIMATION_SLIDE_FROM_BOTTOM = 2
    }

    protected open var animationKind = ANIMATION_DEFAULT

    // Some other stuff
}

现在每个活动都扩展了这个类,并且经常像这样覆盖animationKind

class MyActivity: BaseActivity() {

    override var animationKind = ANIMATION_SLIDE_FROM_RIGHT

    // Some other stuff
}

问题是ANIMATION_SLIDE_FROM_RIGHT 无法访问MyActivity。我要重复一遍,它只发生在手动生成的.apk 上。有趣的是我没有使用multidex,但错误似乎表明BaseActivityclasses3.dex 中。这是我的 gradle 文件:

应用插件:'com.android.application' 应用插件:'kotlin-android' 应用插件:'kotlin-android-extensions' 应用插件:'kotlin-kapt'

android {

    compileSdkVersion 28

    defaultConfig {
        applicationId <package>
        versionCode <versionCode>
        versionName <versionName>
        minSdkVersion 21
        targetSdkVersion 28
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    androidExtensions {
        experimental = true
    }
}

dependencies {

    // Dependencies
}

我尝试使用multidexEnabled false/true,但唯一的变化是false 状态下classes3.dex 后缀消失了。

更新

当然,当我将MyActivityanimationKind 属性更改为1 时,一切正常。

更新 2

删除@JvmStatic 并保护可见性后,它工作正常。

【问题讨论】:

  • @VinayRathod 感谢您的链接。不幸的是,IDE 建议我使用 @JvmStatic,因为“尚不支持在超类伴侣中使用受保护的非 JVM 静态成员。”。我当然可以改成public,但它并不能告诉我有什么问题。
  • @JvmStatic改成@JvmField有帮助吗?
  • @yole 不幸的是只有 @JvmStatic 编译。
  • @Nominalista,请清理并重建它为我工作。

标签: java android kotlin android-gradle-plugin jvm


【解决方案1】:

来自official Kotlin documentation

Java 允许从同一类中的其他类访问受保护的成员 包而 Kotlin 没有,因此 Java 类将具有更广泛的访问权限 到代码

所以,请确保您的BaseActivityMyActivity 在同一个包下。

如果两个 Activity 不在同一个包下,那么它可以通过直接从 Studio 运行完美运行,但是当您生成 .apk 并尝试通过安装该 apk 在设备上运行时它会崩溃 (IllegalAccessError)。

【讨论】:

  • 它没有说明实际问题是什么。此外,companion objectprotected 定义没有任何共同之处。如果我不想在扩展类之外共享这些字段怎么办?
  • 你能以某种方式证明 protected 仅在类位于同一个包中时才有效吗?
  • 我的意思是我找不到在 Kotlin 中只能访问同一包中的受保护字段的信息。
  • 不是官方写的,但我是这么说的。
  • 就我而言,它发生在 java->kotlin 转换期间。文件在同一个包中。最后,我尝试删除 build、app/build 和 .idea 并执行“使缓存无效并重新启动”,然后事情就开始起作用了。 AndroidStudio 4.0.1,Kotlin 版本 1.4.10。当一个问题完全没有意义时,这通常似乎有效。
【解决方案2】:

虽然我不确定为什么会导致 IllegalAccessError,但您应该像这样定义这些常量:

companion object {
    const val ANIMATION_DEFAULT = 0
    const val ANIMATION_SLIDE_FROM_RIGHT = 1
    const val ANIMATION_SLIDE_FROM_BOTTOM = 2
}

这应该可以解决您的问题,否则使用 @JvmField 而不是 @JvmStatic 会是更好的选择。

【讨论】:

  • 如 cmets 中所述,仅适用于受保护字段 @JvmStatic 有效。你是对的,在这种情况下const val 更好,但同样,如果它必须受到保护呢?
  • 当然 :) protected => @JvmStatic
【解决方案3】:

确保您已在调用代码的同一模块中声明了失败的方法。

就我而言,我遇到了以下错误:

java.lang.IllegalAccessError: Method 'boolean[] my.package.common.kotlin.AndroidExtensionsKt.$jacocoInit()' is inaccessible to class 'my.package.ui.first.FirstActivity$viewModel$2' (declaration of 'my.package.ui.first.FirstActivity$viewModel$2' appears in /data/app/my.package.dev-fdHNodmdXHv-b_heK4MXeA==/base.apk!classes8.dex)
    at my.package.ui.first.FirstActivity$viewModel$2.invoke(FirstActivity.kt:18)
    at my.package.ui.first.FirstActivity$viewModel$2.invoke(FirstActivity.kt:14)
    at kotlin.UnsafeLazyImpl.getValue(Lazy.kt:81)
    at my.package.ui.first.FirstActivity.getViewModel(Unknown Source:11)
    at my.package.ui.first.FirstActivity.onCreate(FirstActivity.kt:23)

其中getViewModel()common 模块中声明,FirstActivityapp 模块中声明:

inline fun <reified T : ViewModel> FragmentActivity.getViewModel(
    factory: ViewModelProvider.Factory = ViewModelProvider.NewInstanceFactory()
) = ViewModelProviders.of(this, factory).get(T::class.java)

getViewModel()common 模块移动到app 模块后,没有发现任何问题。

【讨论】:

  • 删除关键字inline 也将解决该错误。但我想知道为什么我不能调用不同模块中的内联函数。
  • 这是我们在 AGP 4.2.0-beta06 中发生的,手动运行 gradle 任务总是给我们IllegalAccessError,看起来需要报告
  • 在 jacoco 中打开了一个问题:github.com/jacoco/jacoco/issues/1171 谷歌也在这里评论:issuetracker.google.com/issues/171802602#comment5
  • 在谷歌问题跟踪器中评论旧问题可能不会得到任何结果。我为此提出了一个新问题。如果@mochadwi 和其他所有人都想给它“加注星标”以帮助 Google 关注它,那就太好了。 issuetracker.google.com/issues/192636549
【解决方案4】:
open class BaseActivity : AppCompatActivity() {
    @JvmField
    protected val ANIMATION_DEFAULT = 0
    @JvmField
    protected val ANIMATION_SLIDE_FROM_RIGHT = 1
    @JvmField
    protected val ANIMATION_SLIDE_FROM_BOTTOM = 2

protected open var animationKind = ANIMATION_DEFAULT

// Some other stuff
}

这个怎么样?

在我看来,Kotlin 还没有完全支持同伴 - jvm 静态成员。

【讨论】: