{"record":{"id":"5de27925ae314f91","repo":"Konloch/bytecode-viewer","slug":"invalid-java-class-file","errorCode":null,"errorMessage":"Invalid Java .class file","messagePattern":"Invalid Java \\.class file","errorType":"exception","errorClass":"ClassFileFormatException","httpStatus":null,"severity":"error","filePath":"src/main/java/the/bytecode/club/bytecodeviewer/decompilers/jdgui/JDGUIClassFileUtil.java","lineNumber":50,"sourceCode":"    public static final char INTERNAL_PACKAGE_SEPARATOR = '/';\n    public static final String CLASS_FILE_SUFFIX = \".class\";\n\n    /*\n     * Lecture rapide de la structure de la classe et extraction du nom du\n     * repoertoire de base.\n     */\n    public static String ExtractDirectoryPath(String pathToClass)\n    {\n        String directoryPath;\n\n        try (FileInputStream fis = new FileInputStream(pathToClass);\n             BufferedInputStream bis = new BufferedInputStream(fis);\n             DataInputStream dis = new DataInputStream(bis))\n        {\n            int magic = dis.readInt();\n            if (magic != ClassFileReader.JAVA_MAGIC_NUMBER)\n            {\n                throw new ClassFileFormatException(\"Invalid Java .class file\");\n            }\n\n            /* int minor_version = */\n            dis.readUnsignedShort();\n            /* int major_version = */\n            dis.readUnsignedShort();\n\n            Constant[] constants = DeserializeConstants(dis);\n\n            /* int access_flags = */\n            dis.readUnsignedShort();\n            int this_class = dis.readUnsignedShort();\n\n            if (this_class > constants.length)\n            {\n                throw new ClassFileFormatException(\"Unknown Java structure\");\n            }\n            Constant c = constants[this_class];","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/Konloch/bytecode-viewer/blob/31430e0033fa220db566b5ef461256727ff6793b/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/jdgui/JDGUIClassFileUtil.java#L32-L68","documentation":"ExtractDirectoryPath reads the first 4 bytes of the given file and compares them to the Java class-file magic number 0xCAFEBABE. If they differ, it throws ClassFileFormatException('Invalid Java .class file'), signaling the path does not point to a real JVM class file. This is a guard so jd-gui glue code never parses a non-class resource as bytecode.","triggerScenarios":"Calling JDGUIClassFileUtil.ExtractDirectoryPath(pathToClass) on a file whose first 4 bytes are not 0xCAFEBABE — e.g. a .java source file, a JAR/ZIP, a text resource, an HTML error page saved with a .class name, a truncated or corrupt file, or a Dex file.","commonSituations":"Globbing a directory and feeding every file (resources, META-INF, .java) to ExtractDirectoryPath instead of only .class files; an unpacked APK where resources were mislabeled; a corrupted download; pointing at the source folder rather than the compiled output.","solutions":["Check the file starts with bytes CA FE BA BE before calling: read the first 4 bytes yourself and skip non-class files.","Ensure you pass only compiled .class files (e.g. from bin/build output), not sources, JARs, or resources.","If the file should be a class but is corrupt, recompile or re-extract it from the original JAR/APK.","If the file is a JAR, extract it first and pass the individual .class entries.","Handle ClassFileFormatException per-file and skip the file instead of letting it abort a batch scan."],"exampleFix":"// before\nString dir = JDGUIClassFileUtil.ExtractDirectoryPath(somePath);\n\n// after\ntry (FileInputStream in = new FileInputStream(somePath)) {\n    int magic = (in.read() << 24) | (in.read() << 16) | (in.read() << 8) | in.read();\n    if (magic != 0xCAFEBABE) return; // not a class file, skip\n}\nString dir = JDGUIClassFileUtil.ExtractDirectoryPath(somePath);","handlingStrategy":"validation","validationCode":"static boolean looksLikeClassFile(String path) throws IOException {\n    try (FileInputStream in = new FileInputStream(path)) {\n        return in.read() == 0xCA && in.read() == 0xFE && in.read() == 0xBA && in.read() == 0xBE;\n    }\n}","typeGuard":"static boolean isJavaClassMagic(byte[] first4) {\n    return first4 != null && first4.length >= 4\n        && first4[0] == (byte)0xCA && first4[1] == (byte)0xFE\n        && first4[2] == (byte)0xBA && first4[3] == (byte)0xBE;\n}","tryCatchPattern":"try {\n    String dir = JDGUIClassFileUtil.ExtractDirectoryPath(path);\n} catch (org.jd.core.v1.service.deserializer.classfile.ClassFileFormatException e) {\n    logger.warn(\"Not a valid class file: {}\", path);\n}","preventionTips":["Pre-check the 0xCAFEBABE magic bytes before calling ExtractDirectoryPath.","Only feed compiled .class files, never .java sources, JARs, or resources.","Filter directory scans to files whose names end in .class and whose size is at least 10 bytes.","Re-verify file integrity (checksum) when files came from network transfers or archives.","Skip-and-log per file so one bad file does not stop batch decompilation."],"tags":["java","class-format","validation","decompiler"],"backgroundTag":"invalid-class-file-format","analyzedSha":"31430e0033fa220db566b5ef461256727ff6793b","analyzedAt":"2026-09-05T18:22:22.725Z","contentChangedAt":"2026-09-05T18:22:22.725Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}