What does setting isAccessible = true do on a KCallable, and what are the risks of reaching private members reflectively?
answer
- isAccessible -> setAccessible(true) on the Java member
- Without it: IllegalCallableAccessException on private
- JPMS: InaccessibleObjectException if package not opened
- Set once, cache the callable
- Runtime bypass only — not a compile-time escape
basics
~20 sisAccessible = true turns off the JVM access check so you can call() or get()/set() a private function, property, or constructor that you'd otherwise be blocked from. It's powerful but bypasses encapsulation and can break under the module system or a SecurityManager.
solid answer
~40 sisAccessible is a property on KCallable (from kotlin.reflect.jvm) that maps to the underlying java.lang.reflect.AccessibleObject.setAccessible(true). Setting it true suppresses Java/Kotlin visibility enforcement, letting you invoke private/internal functions and constructors or read/write private properties (and their backing fields) reflectively; without it, accessing them throws IllegalCallableAccessException. Risks: it defeats encapsulation, couples your code to private implementation details that can change without notice, and on the JVM Platform Module System (JPMS, Java 9+) deep reflection into non-opened modules throws InaccessibleObjectException. It can also be blocked by a SecurityManager. Performance: the access check suppression is per-callable and should be set once and cached. Setting it on a property's getter/setter is separate from setting it on the property itself.
code
kotlin · 11 linesimport kotlin.reflect.full.primaryConstructor
import kotlin.reflect.jvm.isAccessible
class Token private constructor(val value: String)
fun main() {
val ctor = Token::class.primaryConstructor!!
ctor.isAccessible = true
val t = ctor.call("secret")
println(t.value) // secret
}go deeper
Knows isAccessible=true is needed to reach a private member reflectively.
Applies it correctly to functions/properties/constructors and catches IllegalCallableAccessException.
Explains the setAccessible mapping, JPMS/InaccessibleObjectException, SecurityManager, and the encapsulation/brittleness trade-offs.
Sets policy on when reflective private access is acceptable, prefers opens/--add-opens, and designs APIs that avoid the need.
## What isAccessible controls `isAccessible` is an extension property declared in `kotlin.reflect.jvm` on `KCallable<*>`. Setting it `true` calls `setAccessible(true)` on the backing `java.lang.reflect.Method`/`Field`/`Constructor`, **suppressing the language access check**. ```kotlin import kotlin.reflect.full.declaredMemberFunctions import kotlin.reflect.jvm.isAccessible class Secret { private fun token() = "42" } val f = Secret::class.declaredMemberFunctions.first { it.name == "token" } f.isAccessible = true println(f.call(Secret())) // "42" — would throw IllegalCallableAccessException without the line above ``` It applies to functions, constructors, and properties. For properties you can flip it on the property, or specifically on `prop.getter` / `prop.setter`. ## Why you might need it - Reading a private property during serialization/inspection. - Invoking a private constructor in a test or DI container. - Test fixtures that poke at internal state. ## Risks and gotchas - **Encapsulation breakage**: you depend on private details that authors can rename/remove freely — brittle. - **JPMS (Java 9+)**: deep reflection into a module that hasn't `opens` the package throws `InaccessibleObjectException`. `setAccessible` is not a guaranteed override anymore. - **SecurityManager** (where present) can deny `suppressAccessChecks` and throw `SecurityException`. - **Thread-safety / caching**: set it once on a cached callable; flipping repeatedly is wasteful. - It does **not** disable Kotlin `internal`/`private` *compile-time* rules for your own code — it's a runtime bypass only. ## Good practice Prefer public API; reserve `isAccessible` for tests, framework internals, or controlled migration. Document the coupling, and consider `--add-opens` or module `opens` directives for library scenarios instead of silently relying on `setAccessible`.
- Does isAccessible=true always succeed on Java 17+?No. With JPMS, deep reflection into a module that hasn't opened the package throws InaccessibleObjectException; you need an opens directive or --add-opens on the command line.
- Is isAccessible on a property the same as on its getter?Not necessarily — you can set it on the KProperty or specifically on prop.getter/prop.setter; flipping the accessor targets that exact Method.
isAccessible is a master key to a locked room: it gets you in, but the building manager (module system / security policy) can still change the locks or refuse the key.
saying these in an interview costs you the question
- Claiming setAccessible always works regardless of module system
- Treating reflective private access as safe and stable
- Flipping isAccessible on every call instead of caching
- Thinking it bypasses Kotlin compile-time visibility for your own code
- Ignoring SecurityException / InaccessibleObjectException handling