Parse class files with ease. Nearly completely up to the specs at https://docs.oracle.com/javase/specs/jvms/se22/html/jvms-4.html and strongly typed.
First, install @chickenjdk/byteutils
In this example, there is a file called main.class in the dir, with this source code
public class main
{
public static void main(String[] args)
{
System.out.println("Hello, world! Test test!");
}
}
Example use code
const { readClassFile } = require("libclassfile");
const { readFileSync } = require("fs");
const { readableBuffer } = require("@chickenjdk/byteutils");
const testFile = readFileSync("./main.class");
console.log(JSON.stringify(readClassFile(new readableBuffer(testFile))));
Parsed class file of source code with this package
{
"minorVersion": 0,
"majorVersion": 52,
"constantPool": {
"1": {
"class": {
"name": { "value": "java/lang/Object", "tag": 1, "index": 4 },
"tag": 7,
"index": 2
},
"nameAndType": {
"name": { "value": "<init>", "tag": 1, "index": 5 },
"descriptor": { "value": "()V", "tag": 1, "index": 6 },
"tag": 12,
"index": 3
},
"tag": 10,
"index": 1
},
"2": {
"name": { "value": "java/lang/Object", "tag": 1, "index": 4 },
"tag": 7,
"index": 2
},
"3": {
"name": { "value": "<init>", "tag": 1, "index": 5 },
"descriptor": { "value": "()V", "tag": 1, "index": 6 },
"tag": 12,
"index": 3
},
"4": { "value": "java/lang/Object", "tag": 1, "index": 4 },
"5": { "value": "<init>", "tag": 1, "index": 5 },
"6": { "value": "()V", "tag": 1, "index": 6 },
"7": {
"class": {
"name": { "value": "java/lang/System", "tag": 1, "index": 10 },
"tag": 7,
"index": 8
},
"nameAndType": {
"name": { "value": "out", "tag": 1, "index": 11 },
"descriptor": {
"value": "Ljava/io/PrintStream;",
"tag": 1,
"index": 12
},
"tag": 12,
"index": 9
},
"tag": 9,
"index": 7
},
"8": {
"name": { "value": "java/lang/System", "tag": 1, "index": 10 },
"tag": 7,
"index": 8
},
"9": {
"name": { "value": "out", "tag": 1, "index": 11 },
"descriptor": { "value": "Ljava/io/PrintStream;", "tag": 1, "index": 12 },
"tag": 12,
"index": 9
},
"10": { "value": "java/lang/System", "tag": 1, "index": 10 },
"11": { "value": "out", "tag": 1, "index": 11 },
"12": { "value": "Ljava/io/PrintStream;", "tag": 1, "index": 12 },
"13": {
"value": { "value": "Hello, world! Test test!", "tag": 1, "index": 14 },
"tag": 8,
"index": 13
},
"14": { "value": "Hello, world! Test test!", "tag": 1, "index": 14 },
"15": {
"class": {
"name": { "value": "java/io/PrintStream", "tag": 1, "index": 18 },
"tag": 7,
"index": 16
},
"nameAndType": {
"name": { "value": "println", "tag": 1, "index": 19 },
"descriptor": {
"value": "(Ljava/lang/String;)V",
"tag": 1,
"index": 20
},
"tag": 12,
"index": 17
},
"tag": 10,
"index": 15
},
"16": {
"name": { "value": "java/io/PrintStream", "tag": 1, "index": 18 },
"tag": 7,
"index": 16
},
"17": {
"name": { "value": "println", "tag": 1, "index": 19 },
"descriptor": { "value": "(Ljava/lang/String;)V", "tag": 1, "index": 20 },
"tag": 12,
"index": 17
},
"18": { "value": "java/io/PrintStream", "tag": 1, "index": 18 },
"19": { "value": "println", "tag": 1, "index": 19 },
"20": { "value": "(Ljava/lang/String;)V", "tag": 1, "index": 20 },
"21": {
"name": { "value": "main", "tag": 1, "index": 22 },
"tag": 7,
"index": 21
},
"22": { "value": "main", "tag": 1, "index": 22 },
"23": { "value": "Code", "tag": 1, "index": 23 },
"24": { "value": "LineNumberTable", "tag": 1, "index": 24 },
"25": { "value": "([Ljava/lang/String;)V", "tag": 1, "index": 25 },
"26": { "value": "SourceFile", "tag": 1, "index": 26 },
"27": { "value": "main.java", "tag": 1, "index": 27 }
},
"accessFlags": {
"isPublic": true,
"isFinal": false,
"isSuper": true,
"isInterface": false,
"isAbstract": false,
"isAnnotation": false,
"isEnum": false,
"isModule": false
},
"thisClass": {
"name": { "value": "main", "tag": 1, "index": 22 },
"tag": 7,
"index": 21
},
"superClass": {
"name": { "value": "java/lang/Object", "tag": 1, "index": 4 },
"tag": 7,
"index": 2
},
"interfaces": [],
"fields": [],
"methods": [
{
"accessFlags": {
"isPublic": true,
"isPrivate": false,
"isProtected": false,
"isStatic": false,
"isFinal": false,
"isSynchronized": false,
"isBridge": false,
"isVarargs": false,
"isNative": false,
"isAbstract": false,
"isStrict": false,
"isSynthetic": false
},
"name": { "value": "<init>", "tag": 1, "index": 5 },
"descriptor": { "value": "()V", "tag": 1, "index": 6 },
"attributes": [
{
"name": "Code",
"maxStack": 1,
"maxLocals": 1,
"code": [42, 183, 0, 1, 177],
"exceptionTable": [],
"attributes": [
{
"name": "LineNumberTable",
"lineNumberTable": [{ "startPc": 0, "lineNumber": 1 }]
}
]
}
]
},
{
"accessFlags": {
"isPublic": true,
"isPrivate": false,
"isProtected": false,
"isStatic": true,
"isFinal": false,
"isSynchronized": false,
"isBridge": false,
"isVarargs": false,
"isNative": false,
"isAbstract": false,
"isStrict": false,
"isSynthetic": false
},
"name": { "value": "main", "tag": 1, "index": 22 },
"descriptor": {
"value": "([Ljava/lang/String;)V",
"tag": 1,
"index": 25
},
"attributes": [
{
"name": "Code",
"maxStack": 2,
"maxLocals": 1,
"code": [178, 0, 7, 18, 13, 182, 0, 15, 177],
"exceptionTable": [],
"attributes": [
{
"name": "LineNumberTable",
"lineNumberTable": [
{ "startPc": 0, "lineNumber": 5 },
{ "startPc": 8, "lineNumber": 6 }
]
}
]
}
]
}
],
"attributes": [
{
"name": "SourceFile",
"sourcefile": { "value": "main.java", "tag": 1, "index": 27 }
}
]
}