oracle/graal · error · IllegalArgumentException

Directed inlining rule has an empty {componentName} filter o

Error message

Directed inlining rule has an empty {componentName} filter or bci: {ruleSpec}

What it means

parseMethodSpec (DirectedInliningRules.java:330) handles optional '@bci' suffixes on caller/callee specs to pin a rule to a specific invocation bytecode index. If either side of '@' is empty (e.g., 'A.m@' or '@42'), it throws this IllegalArgumentException naming which component was malformed.

Source

Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/inlining/DirectedInliningRules.java:330

        }

        ParsedCalleeSpec callee = parseCalleeSpec(calleeSpec, ruleSpec);

        return new Rule(ruleSpec,
                        callerFilters,
                        callerBcis,
                        new ComponentFilter(parseSinglePositiveMethodFilter(callee.methodSpec(), "callee", ruleSpec), callee.receiverTypes()));
    }

    private static ParsedMethodSpec parseMethodSpec(String methodSpec, String componentName, String ruleSpec) {
        int bci = ANY_BCI;
        int bciSeparator = findLastTopLevel(methodSpec, '@');
        String parsedMethodSpec = methodSpec;
        if (bciSeparator >= 0) {
            String bciSpec = methodSpec.substring(bciSeparator + 1).trim();
            parsedMethodSpec = methodSpec.substring(0, bciSeparator).trim();
            if (parsedMethodSpec.isEmpty() || bciSpec.isEmpty()) {
                throw new IllegalArgumentException("Directed inlining rule has an empty " + componentName + " filter or bci: " + ruleSpec);
            }
            bci = Integer.parseInt(bciSpec);
        }
        return new ParsedMethodSpec(parsedMethodSpec, bci);
    }

    private static ParsedCalleeSpec parseCalleeSpec(String calleeSpec, String ruleSpec) {
        int typeFilterStart = findTopLevel(calleeSpec, "{");
        if (typeFilterStart < 0) {
            if (findTopLevel(calleeSpec, "}") >= 0) {
                throw invalidRule(ruleSpec);
            }
            return new ParsedCalleeSpec(calleeSpec, ReceiverTypeFilter.EMPTY_ARRAY);
        }

        int typeFilterEnd = findMatchingBrace(calleeSpec, typeFilterStart);
        if (typeFilterEnd < 0) {
            throw invalidRule(ruleSpec);

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Supply both halves: a method filter followed by an integer bci, e.g., 'com.foo.A.f@17'
  2. Drop the '@bci' suffix entirely to match any bci
  3. Remember '@' means 'at this bytecode index', not a path separator

Example fix

# before
inline : com.foo.A.f@ -> com.bar.B.g

# after
inline : com.foo.A.f@17 -> com.bar.B.g
Defensive patterns

Strategy: validation

Validate before calling

if (spec.indexOf('@') >= 0) {
    String[] halves = spec.split("@", -1);
    assert halves.length == 2 && !halves[0].trim().isEmpty() && halves[1].trim().matches("\\d+") : spec;
}

Prevention

When it happens

Trigger: A rule component like 'com.foo.A.f@' (missing bci), '@17' (missing method filter), or 'com.foo.A.f @ ' where trimming yields an empty half.

Common situations: Hand-editing bcis into rules; removing a method name but leaving the bci; assuming '@' is a separator between caller and callee rather than a bci marker.

Related errors


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