Skip to content

Instantly share code, notes, and snippets.

@ahausmann
Last active August 29, 2015 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ahausmann/195077e98b35e5491620 to your computer and use it in GitHub Desktop.
Save ahausmann/195077e98b35e5491620 to your computer and use it in GitHub Desktop.
Java Class file structure for Okteta, extended from example with field_info, method_info and attribute_info
var constantType = {
'Class': 7,
'Fieldref': 9,
'Methodref': 10,
'InterfaceMethodref': 11,
'String': 8,
'Integer': 3,
'Float': 4,
'Long': 5,
'Double': 6,
'NameAndType': 12,
'Utf8': 1,
'MethodHandle': 15,
'MethodType': 16,
'InvokeDynamic': 18
};
var classAccessFlags = {
'public': 0x0001,
'final': 0x0010,
'super': 0x0020,
'interface': 0x0200,
'abstract': 0x0400,
'synthetic': 0x1000,
'annotation': 0x2000,
'enum': 0x4000
};
/** represents an index into the constant pool array (actually just a uint16) */
function cpIndex() {
function validateCpIndex(root) {
return this.value < root.constant_pool.length;
}
//TODO custom to string
var ret = uint16();
ret.typeName = "cp_index";
ret.validationFunc = validateCpIndex;
return ret;
}
/* create an object corresponding to the class file cp_info union */
function cp_info() {
//the list of possible interpretations of this structure:
var cpAlternatives = [
//this is the really verbose way of defining an alternative in the tagged union:
{
structName: 'CONSTANT_Class_info',
selectIf: function(root) {
return this.tag.value == constantType.Class;
},
fields: {
name_index: cpIndex()
}
},
// we can also use a less verbose version using the predefined alternative() function
alternative(function(root) { return this.tag.value == constantType.String; }, //selectIf
{ name_index: cpIndex() }, //fields
'CONSTANT_String_info'), //structName
//it can be even shorter since there is only one value in this tagged union that can be used to decide
//therefore just passing the value as an argument is enough
alternative(constantType.Integer, { value : int32() }, 'CONSTANT_Integer_info'),
//obviously this also works if we define the object manually
{
structName: 'CONSTANT_Float_info',
selectIf: constantType.Float,
fields: { value: float() }
},
//just use the shortest syntax for the remaining alternatives
alternative(constantType.Long, {
value : int64()
}, 'CONSTANT_Long_info'),
alternative(constantType.Double, {
value : double()
}, 'CONSTANT_Double_info'),
alternative(constantType.Fieldref, {
class_index: cpIndex(),
name_and_type_index: cpIndex()
}, 'CONSTANT_Fieldref_info'),
alternative(constantType.Methodref, {
class_index: cpIndex(),
name_and_type_index: cpIndex()
}, 'CONSTANT_Methodref_info'),
alternative(constantType.InterfaceMethodref, {
class_index: cpIndex(),
name_and_type_index: cpIndex()
}, 'CONSTANT_InterfaceMethodref_info'),
alternative(constantType.NameAndType, {
name_index: cpIndex(),
descriptor_index: cpIndex()
}, 'CONSTANT_NameAndType_info'),
alternative(constantType.MethodHandle, {
reference_kind: uint8(),
reference_index: cpIndex()
}, 'CONSTANT_MethodHandle_info'),
alternative(constantType.MethodType, {
descriptor_index: cpIndex()
}, 'CONSTANT_MethodType_info'),
alternative(constantType.InvokeDynamic, {
bootstrap_method_attr_index: cpIndex(),
name_and_type_index: cpIndex()
}, 'CONSTANT_InvokeDynamic_info'),
alternative(constantType.Utf8, {
length: uint16(),
bytes: string('utf8').set({
maxByteCount: 0,
updateFunc: function() { this.maxByteCount = this.parent.length.value; }
})
}, 'CONSTANT_Utf8_info')
];
/* first argument is the fixed elements, second is the alternatives, and last is the default fields (if none of the alternatives match) */
return taggedUnion({ tag: enumeration('ConstantType', uint8(), constantType)}, cpAlternatives, { dummy: uint8() });
}
function attribute_info() {
/*
attribute_info {
u2 name_index;
u4 length;
u1 info[length];
}
*/
var s = struct({
name_index: cpIndex(),
length: uint32(),
info: array(uint8(), function(root) { return this.parent.length.value; }),
});
s.typeName = "attribute_info";
return s;
}
function field_info() {
/*
field_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}
*/
var s = struct({
access_flags: access_flags(),
name_index: cpIndex(),
descriptor_index: cpIndex(),
attributes_count: uint16(),
attributes: array(attribute_info(), function(root) { return this.parent.attributes_count.value; }),
});
s.typeName = "field_info";
return s;
}
function method_info() {
/*
method_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}
*/
var s = struct({
access_flags: access_flags(),
name_index: cpIndex(),
descriptor_index: cpIndex(),
attributes_count: uint16(),
attributes: array(attribute_info(), function(root) { return this.parent.attributes_count.value; }),
});
s.typeName = "method_info";
return s;
}
function access_flags() {
return flags('ClassAccessFlags', uint16(), classAccessFlags);
}
function init() {
//from http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html
/*
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
*/
var classFile = struct({
magic: uint32(),
minor_version: uint16(),
major_version: uint16(),
constant_pool_count: uint16(),
/* length is always constant_pool_count - 1 */
constant_pool: array(cp_info(), function(root) { return root.constant_pool_count.value - 1; }),
access_flags: flags('ClassAccessFlags', uint16(), classAccessFlags),
this_class: cpIndex(),
super_class: cpIndex(),
interfaces_count: uint16(),
interfaces: array(cpIndex(), function(root) { return root.interfaces_count.value; }),
fields_count: uint16(),
fields: array(field_info(), function(root) { return root.fields_count.value; }),
methods_count: uint16(),
methods: array(method_info(), function(root) { return root.methods_count.value; }),
attributes_count: uint16(),
attributes: array(attribute_info(), function(root) { return root.attributes_count.value; }),
});
//classfile is always stored in big endian
classFile.byteOrder = "bigEndian";
return classFile;
}
[Desktop Entry]
Encoding=UTF-8
Icon=application-x-java
Type=Service
ServiceTypes=KPluginInfo
Name=Java .class file format
Name[ca]=Format de fitxer .class del Java
Name[da]=Java .class-filformat
Name[de]=Java-„.class“-Dateiformat
Name[en_GB]=Java .class file format
Name[es]=Formato de archivo .class de Java
Name[fi]=Javan .class-tiedostomuoto
Name[fr]=Format de fichier « .class » Java
Name[gl]=Formato de ficheiro «.class» de Java
Name[hu]=Java .class fájlformátum
Name[it]=Formato di file .class di Java
Name[ko]=Java .class 파일 형식
Name[nl]=Bestandsformaat van Java .class
Name[pl]=Format plików .class Javy
Name[pt]=Formato de ficheiro .class do Java
Name[pt_BR]=Formato de arquivo .class do Java
Name[ru]=Классы Java
Name[sk]=Formát súborov Java .class
Name[sr]=Формат јаванског .class фајла
Name[sr@ijekavian]=Формат јаванског .class фајла
Name[sr@ijekavianlatin]=Format javanskog .class fajla
Name[sr@latin]=Format javanskog .class fajla
Name[sv]=Java .class-filformat
Name[tr]=Java .class dosya biçimi
Name[uk]=Формат файлів .class Java
Name[x-test]=xxJava .class file formatxx
Name[zh_CN]=Java .class 文件格式
Name[zh_TW]=Java .class 檔案格式
Comment=still very incomplete!!!
Comment[ca]=Encara està molt incomplet!
Comment[da]=stadig langt fra færdigt!!!
Comment[de]=Noch sehr unvollständig
Comment[en_GB]=still very incomplete!!!
Comment[es]=Todavía bastante incompleto
Comment[fi]=vielä erittäin keskeneräinen!
Comment[fr]=Encore très incomplet !!!
Comment[gl]=Aínda está moi incompleto!
Comment[hu]=még mindig nagyon hiányos!!!
Comment[it]=Ancora molto incompleto!
Comment[ko]=여전히 불완전합니다!!!
Comment[nl]=nog steeds erg onvolledig!!!
Comment[pl]=nadal bardzo nieukończone!!!
Comment[pt]=ainda muito incompleto!!!
Comment[pt_BR]=ainda muito incompleto!!!
Comment[ru]=В процессе разработки
Comment[sk]=stále veľmi nekompletné!!!
Comment[sr]=Још увек врло непотпуно!
Comment[sr@ijekavian]=Још увек врло непотпуно!
Comment[sr@ijekavianlatin]=Još uvek vrlo nepotpuno!
Comment[sr@latin]=Još uvek vrlo nepotpuno!
Comment[sv]=Fortfarande mycket ofullständigt!
Comment[tr]=hala çok eksik!!!
Comment[uk]=Все ще доволі неповний!
Comment[x-test]=xxstill very incomplete!!!xx
Comment[zh_CN]=仍非常不完整!!!
Comment[zh_TW]=仍然不完整!
X-KDE-PluginInfo-Author=Alex Richardson & Alexander Hausmann
X-KDE-PluginInfo-Email=alex.richardson@gmx.de
X-KDE-PluginInfo-Name=classfile
X-KDE-PluginInfo-Version=0.2
X-KDE-PluginInfo-Website=http://www.plugin.org/
X-KDE-PluginInfo-Category=structure/js
X-KDE-PluginInfo-License=GPLv3
X-KDE-PluginInfo-EnabledByDefault=false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment