oracle/graal · error · IllegalAccessError

illegal access linking method 'jdk.jfr.internal.event.EventW

Error message

illegal access linking method 'jdk.jfr.internal.event.EventWriterFactory.getEventWriter(long)'

What it means

lookupMethod special-cases jdk.jfr.internal.event.EventWriterFactory.getEventWriter(long): that internal method may only be linked from JFR-instrumented bytecode, which this provider never parses. Resolving it through ClassfileBytecodePool therefore throws IllegalAccessError immediately, mirroring the JVM's access check and failing fast instead of producing an invalid linkage.

Source

Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/classfile/ClassfileConstantPool.java:179

    @Override
    public JavaMethod lookupMethod(int index, int opcode) {
        if (opcode == Bytecodes.INVOKEDYNAMIC) {
            throw new GraalError("INVOKEDYNAMIC not supported by" + ClassfileBytecodeProvider.class.getSimpleName());
        }
        return get(ExecutableRef.class, index).resolve(this, opcode);
    }

    @Override
    public JavaMethod lookupMethod(int index, int opcode, ResolvedJavaMethod caller) {
        if (opcode == Bytecodes.INVOKEDYNAMIC) {
            throw new GraalError("INVOKEDYNAMIC not supported by" + ClassfileBytecodeProvider.class.getSimpleName());
        }
        ResolvedJavaMethod result = get(ExecutableRef.class, index).resolve(this, opcode);
        if (result != null && result.getName().equals("getEventWriter") && result.getDeclaringClass().getName().equals("Ljdk/jfr/internal/event/EventWriterFactory;")) {
            // Only JFR transformed methods can call
            // jdk.jfr.internal.event.EventWriterFactory.getEventWriter(long)
            // and this ClassfileBytecode will never be used to load such a class.
            throw new IllegalAccessError("illegal access linking method 'jdk.jfr.internal.event.EventWriterFactory.getEventWriter(long)'");
        }
        return result;
    }

    @Override
    public List<BootstrapMethodInvocation> lookupBootstrapMethodInvocations(boolean invokeDynamic) {
        throw GraalError.unimplementedOverride(); // ExcludeFromJacocoGeneratedReport
    }

    @Override
    public JavaType lookupType(int index, int opcode) {
        return get(ClassRef.class, index).resolve(this);
    }

    @Override
    public JavaType lookupReferencedType(int index, int opcode) {
        switch (opcode) {
            case Bytecodes.CHECKCAST:

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Do not call jdk.jfr.internal.* from your own code; use the public jdk.jfr API (Event, EventFactory, Recording).
  2. If you copied HotSpot/JFR-internal source into replacements, remove or stub the getEventWriter call path.

Example fix

// before
EventWriter w = EventWriterFactory.getEventWriter(eventStruct); // internal API

// after
MyEvent ev = new MyEvent(); // extends jdk.jfr.Event (public API)
ev.commit();
Defensive patterns

Strategy: try-catch

Try / catch

try {
    JavaMethod m = pool.lookupMethod(index, opcode, caller);
} catch (IllegalAccessError e) {
    // A resolution attempt on jdk.jfr.internal EventWriterFactory.getEventWriter
    // means internal JFR APIs leaked into parsed bytecode; fix the caller, don't retry
    throw new IllegalStateException("Internal JFR API referenced from parsed bytecode", e);
}

Prevention

When it happens

Trigger: Bytecode parsed by ClassfileBytecodeProvider resolves a call whose constant-pool target is EventWriterFactory.getEventWriter(long).

Common situations: Replacement/snippet code (or copied JFR internals) attempting to call the internal event-writer factory directly; using jdk.jfr.internal types instead of the public jdk.jfr API.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/ed2d9986c55ffebc. Report an issue: GitHub.