Tencent/matrix · error · ClassNotFoundException

Field_ViewRootImpl_mView not found

Error message

Field_ViewRootImpl_mView not found

What it means

prepareWindowGlobal() also requires the reflected ViewRootImpl 'mView' field (Field_ViewRootImpl_mView) to walk from window roots to the root view. If that reflection failed, it throws ClassNotFoundException('Field_ViewRootImpl_mView not found') even when mRoots resolved.

Solutions

  1. Catch ClassNotFoundException around the overlay/window query APIs and degrade gracefully.
  2. Check hidden-API access policy for the device's Android version; whitelist via debug hidden-api exemptions only in development.
  3. Update Matrix to a version matching the current Android/ROM reflection surface.

Example fix

// before
val has = OverlayWindowLifecycleOwner.hasOverlayWindow()
// after
val has = try {
    OverlayWindowLifecycleOwner.hasOverlayWindow()
} catch (e: ClassNotFoundException) {
    MatrixLog.w(TAG, "ViewRootImpl.mView unavailable", e)
    false
}
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

val has = try {
    OverlayWindowLifecycleOwner.hasOverlayWindow()
} catch (e: ClassNotFoundException) {
    MatrixLog.w(TAG, "ViewRootImpl.mView reflection failed", e)
    false
}

Prevention

When it happens

Trigger: Calling hasVisibleWindow(), hasOverlayWindow(), or getAllViews() on a device where ReflectUtils fails to resolve the mView field on android.view.ViewRootImpl.

Common situations: Newer Android versions or OEM ROMs where hidden-API restrictions block reflective access to ViewRootImpl.mView while WindowManagerGlobal.mRoots is still accessible.

Related errors


AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08). Data as JSON: /api/errors/e6049cc8b1bc6db7. Report an issue: GitHub.

Appendix: source

Thrown at matrix/matrix-android/matrix-android-lib/src/main/java/com/tencent/matrix/lifecycle/owners/OverlayWindowLifecycleOwner.kt:130

    private fun prepareWindowGlobal() {
        if (WindowManagerGlobal_mRoots == null) {
            if (fallbacked) {
                throw ClassNotFoundException("WindowManagerGlobal_mRoots not found")
            }
            MatrixLog.i(TAG, "monitor disabled, fallback init")
            fallbacked = true
            WindowManagerGlobal_mRoots = safeLetOrNull(TAG) {
                Class.forName("android.view.WindowManagerGlobal").let {
                    val instance = ReflectUtils.invoke<Any>(it, "getInstance", null)
                    ReflectUtils.get(it, "mRoots", instance)
                }
            }
        }
        if (WindowManagerGlobal_mRoots == null) {
            throw ClassNotFoundException("WindowManagerGlobal_mRoots not found")
        }
        if (Field_ViewRootImpl_mView == null) {
            throw ClassNotFoundException("Field_ViewRootImpl_mView not found")
        }
    }

    /**
     * including Activity window, for fallback checks
     */
    fun hasVisibleWindow() = safeLet(TAG, log = true, defVal = false) {
        prepareWindowGlobal()
        return@safeLet WindowManagerGlobal_mRoots!!.any {
            val v = Field_ViewRootImpl_mView!!.get(it)
            // windowVisibility is determined by app vibility
            // until the PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY is set, which is blocked in Q
            return@any v != null && View.VISIBLE == v.visibility && View.VISIBLE == v.windowVisibility
        }
    }

    fun hasOverlayWindow() = if (injected) {
        active()

View on GitHub (pinned to 3b8293bd65)