oracle/graal · error · IllegalArgumentException

Class name in signature contains '.' at index

Error message

Class name in signature contains '.' at index 

What it means

IllegalArgumentException from SignatureUtil.parseParameterSignature: while scanning an 'L...' class name inside a descriptor, a '.' is found in the fully-qualified class name. JVMS descriptors use '/' as the package separator ('Ljava/lang/String;'); a '.' indicates a Java-source-style name ('Ljava.lang.String;') slipped in, which would silently produce wrong resolved types, so the parser rejects it explicitly (message includes the offending index and full signature).

Source

Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/SignatureUtil.java:141

        }
    }

    /**
     * Checks if the given signature can be successfully parsed by
     * {@link #parseSignature(String, List)}.
     *
     * @param signature the signature to check
     * @param acceptMissingReturnType whether a signature without a return type is considered to be
     *            valid
     * @return whether the signature can be successfully parsed
     */
    public static boolean isSignatureValid(String signature, boolean acceptMissingReturnType) {
        return parseSignatureInternal(signature, null, false, acceptMissingReturnType) != null;
    }

    private static <T> T throwOrReturn(boolean shouldThrow, T returnValue, String errorMessage) {
        if (shouldThrow) {
            throw new IllegalArgumentException(errorMessage);
        } else {
            return returnValue;
        }
    }
}

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Use the internal form: replace '.' with '/' — or better, use a helper like JVMCI's MetaUtil.toInternalName or signature.toString() from a ResolvedJavaMethod.
  2. If building from reflection, use MethodType.toMethodDescriptorString() which emits the correct format.
  3. Pre-validate with SignatureUtil.isSignatureValid before parsing untrusted strings.

Example fix

// before
String d = "L" + clazz.getName() + ";"; // Ljava.lang.String;

// after
String d = "L" + clazz.getName().replace('.', '/') + ";"; // Ljava/lang/String;
// or: MethodType.fromMethodDescriptorString(...).toMethodDescriptorString()
Defensive patterns

Strategy: validation

Validate before calling

// Normalize dotted names to internal form before parsing
String normalized = sig.replace('.', '/');
boolean ok = SignatureUtil.isSignatureValid(normalized, false);
// But prefer generating from JVMCI/Reflection: MethodType...toMethodDescriptorString()

Type guard

static boolean usesInternalNames(String descriptor) {
    // no '.' may appear anywhere inside L...; segments
    return !descriptor.chars().anyMatch(c -> c == '.');
}

Try / catch

try {
    SignatureUtil.parseSignature(sig, params);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("contains '.'")) {
        SignatureUtil.parseSignature(sig.replace('.', '/'), params);
    } else throw e;
}

Prevention

When it happens

Trigger: Calling SignatureUtil.parseSignature with a descriptor built via Class.getName() (which returns dotted names like 'java.lang.String') instead of the internal slash form — e.g. 'L' + clazz.getName() + ';' yields 'Ljava.lang.String;' and trips this check at the first '.'.

Common situations: Building descriptors from reflection: Class.getName() vs the internal name; copy-pasting signatures from javadoc/source instead of from javap -s output; string-replacing only some dots.

Related errors


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