IllegalAccessError:类无法访问方法

时间:2018-07-20 05:25:09

标签: java android kotlin android-gradle jvm

我有一个非常奇怪的错误,因为它仅在从生成的.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后缀消失了。

更新

当然,当我将MyActivity的{​​{1}}属性更改为animationKind时,一切正常。

更新2

在删除1并保护可见性后,它可以正常工作。

4 个答案:

答案 0 :(得分:6)

来自official Kotlin documentation

  

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

因此,请确保您的flex: 15BaseActivity位于同一软件包中。

如果两个活动都不在同一个程序包中,则可以通过直接从Studio直接运行来完美运行,但是在生成.apk并尝试通过安装该apk在设备上运行时会崩溃(IllegalAccessError)。

答案 1 :(得分:0)

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

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

那应该可以解决您的问题,否则使用@JvmField代替@JvmStatic会是一个更好的选择。

答案 2 :(得分:0)

确保已声明与调用代码同一模块内失败的方法。

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

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,在FirstActivity模块中声明了app的地方:

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

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

答案 3 :(得分:0)

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 静态成员。