Konloch/bytecode-viewer · error · ClassFileFormatException
Invalid internal class name
Error message
Invalid internal class name
What it means
JDGUIClassFileUtil maps a JVM internal class name (slashes instead of dots) to its .class file path inside an archive. When the computed path suffix (internal name with '/' replaced by the platform separator, plus '.class') cannot be located in the discovered path, it throws ClassFileFormatException('Invalid internal class name'), aborting decompilation of that entry. This protects the decompiler from operating on entries that don't correspond to a real class file layout.
Source
Thrown at src/main/java/the/bytecode/club/bytecodeviewer/decompilers/jdgui/JDGUIClassFileUtil.java:87
if ((c == null) || (c.getTag() != Constant.CONSTANT_Class))
{
throw new ClassFileFormatException("Invalid constant pool");
}
c = constants[((ConstantClass) c).getNameIndex()];
if ((c == null) || (c.getTag() != Constant.CONSTANT_Utf8))
{
throw new ClassFileFormatException("Invalid constant pool");
}
String internalClassName = ((ConstantUtf8) c).getValue();
String pathSuffix = internalClassName.replace(INTERNAL_PACKAGE_SEPARATOR, File.separatorChar) + CLASS_FILE_SUFFIX;
int index = pathToClass.indexOf(pathSuffix);
if (index < 0)
{
throw new ClassFileFormatException("Invalid internal class name");
}
directoryPath = pathToClass.substring(0, index);
}
catch (IOException e)
{
directoryPath = null;
e.printStackTrace();
}
return directoryPath;
}
public static String ExtractInternalPath(String directoryPath, String pathToClass)
{
if ((directoryPath == null) || (pathToClass == null) || !pathToClass.startsWith(directoryPath))
return null;
View on GitHub (pinned to 31430e0033)
Solutions
- Verify the jar's directory layout matches each class's package (com/foo/Bar.class for com.foo.Bar)
- Re-decompile from the original, un-obfuscated jar or disable obfuscation in the build
- If it's an inner class, ensure Outer$Inner.class entries are present in the archive
- Catch ClassFileFormatException and fall back to another decompiler (e.g. CFR, FernFlower) for that entry
- If the jar was built on another OS, normalize paths instead of relying on File.separatorChar
Example fix
// before
String pathSuffix = internalClassName.replace('.', '/') + ".class";
int index = pathToClass.indexOf(pathSuffix);
if (index < 0) throw new ClassFileFormatException("Invalid internal class name");
// after
String normalized = internalClassName.replace('.', '/').replace('$', '/');
String pathSuffix = normalized + ".class";
int index = pathToClass.indexOf(pathSuffix);
if (index < 0) {
index = pathToClass.indexOf(internalClassName.replace('.', '/') + ".class"); // retry with $ kept
}
if (index < 0) throw new ClassFileFormatException("Invalid internal class name: " + internalClassName); Defensive patterns
Strategy: try-catch
Validate before calling
String expected = internalClassName.replace('.', '/') + ".class";
boolean exists = classLoader.getResource(expected) != null || jarEntries.contains(expected);
if (!exists) throw new IllegalArgumentException("No class file for " + internalClassName); Type guard
boolean isValidInternalName(String name) {
return name != null && name.matches("[\\w/$]+");
} Try / catch
try {
decompileWithJdGui(internalClassName, bytes);
} catch (ClassFileFormatException e) {
LOGGER.warn("Skipping " + internalClassName + ": " + e.getMessage());
fallbackDecompiler.decompile(internalClassName, bytes);
} Prevention
- Check the jar entry exists for the class's binary name before decompiling
- Keep class file paths aligned with package declarations; avoid manual repackaging
- Obtain internal names from the bytecode (e.g. ASM Type.getInternalName) rather than file paths
- Fall back to a second decompiler when one fails
- Handle inner-class binary names (Outer$Inner) explicitly
When it happens
Trigger: Calling the JD-GUI decompiler on a class whose internal name does not match the archive's directory structure: e.g. obfuscated/renamed class names, class names containing dots or special characters that were replaced by INTERNAL_PACKAGE_SEPARATOR, anonymous/inner classes whose binary name (Outer$Inner) doesn't map to a file the util can find, or decompiling a non-class resource mistakenly routed to this util.
Common situations: Decompiling obfuscated jars (ProGuard/Rename targets) where names no longer match paths; jars built on different OSes with mismatched path separators; jars repackaged so class files move relative to their package path; inner/anonymous classes in frameworks like Mockito or GUI builders; feeding a .class resource that lives outside the expected package directory.
Related errors
- Unable to resolve class-filetype.
- Unable to resolve type.
- '${file.getAbsolutePath()}' not found.
- Invalid Java .class file
- Unknown Java structure
AI-assisted analysis of Konloch/bytecode-viewer@31430e0033 (2026-09-05).
Data as JSON: /api/errors/3d76cde4b01b52f3.
Report an issue: GitHub.