.class file format: Lua parsing library

File extension

class

KS implementation details

License: CC0-1.0

References

This page hosts a formal specification of .class file format using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Lua source code to parse .class file format

java_class.lua

-- This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
--
-- This file is compatible with Lua 5.3

local class = require("class")
require("kaitaistruct")
local utils = require("utils")
local stringstream = require("string_stream")
local enum = require("enum")
local str_decode = require("string_decode")

-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.1)
JavaClass = class.class(KaitaiStruct)

function JavaClass:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass:_read()
  self.magic = self._io:read_bytes(4)
  if not(self.magic == "\202\254\186\190") then
    error("not equal, expected " ..  "\202\254\186\190" .. ", but got " .. self.magic)
  end
  self.version_minor = self._io:read_u2be()
  self.version_major = self._io:read_u2be()
  self.constant_pool_count = self._io:read_u2be()
  self.constant_pool = {}
  for i = 0, (self.constant_pool_count - 1) - 1 do
    self.constant_pool[i + 1] = JavaClass.ConstantPoolEntry(utils.box_unwrap((i ~= 0) and utils.box_wrap(self.constant_pool[(i - 1) + 1].is_two_entries) or (false)), self._io, self, self._root)
  end
  self.access_flags = self._io:read_u2be()
  self.this_class = self._io:read_u2be()
  self.super_class = self._io:read_u2be()
  self.interfaces_count = self._io:read_u2be()
  self.interfaces = {}
  for i = 0, self.interfaces_count - 1 do
    self.interfaces[i + 1] = self._io:read_u2be()
  end
  self.fields_count = self._io:read_u2be()
  self.fields = {}
  for i = 0, self.fields_count - 1 do
    self.fields[i + 1] = JavaClass.FieldInfo(self._io, self, self._root)
  end
  self.methods_count = self._io:read_u2be()
  self.methods = {}
  for i = 0, self.methods_count - 1 do
    self.methods[i + 1] = JavaClass.MethodInfo(self._io, self, self._root)
  end
  self.attributes_count = self._io:read_u2be()
  self.attributes = {}
  for i = 0, self.attributes_count - 1 do
    self.attributes[i + 1] = JavaClass.AttributeInfo(self._io, self, self._root)
  end
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.5)
JavaClass.FloatCpInfo = class.class(KaitaiStruct)

function JavaClass.FloatCpInfo:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.FloatCpInfo:_read()
  self.value = self._io:read_f4be()
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7)
JavaClass.AttributeInfo = class.class(KaitaiStruct)

function JavaClass.AttributeInfo:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.AttributeInfo:_read()
  self.name_index = self._io:read_u2be()
  self.attribute_length = self._io:read_u4be()
  local _on = self.name_as_str
  if _on == "SourceFile" then
    self._raw_info = self._io:read_bytes(self.attribute_length)
    local _io = KaitaiStream(stringstream(self._raw_info))
    self.info = JavaClass.AttributeInfo.AttrBodySourceFile(_io, self, self._root)
  elseif _on == "LineNumberTable" then
    self._raw_info = self._io:read_bytes(self.attribute_length)
    local _io = KaitaiStream(stringstream(self._raw_info))
    self.info = JavaClass.AttributeInfo.AttrBodyLineNumberTable(_io, self, self._root)
  elseif _on == "Exceptions" then
    self._raw_info = self._io:read_bytes(self.attribute_length)
    local _io = KaitaiStream(stringstream(self._raw_info))
    self.info = JavaClass.AttributeInfo.AttrBodyExceptions(_io, self, self._root)
  elseif _on == "Code" then
    self._raw_info = self._io:read_bytes(self.attribute_length)
    local _io = KaitaiStream(stringstream(self._raw_info))
    self.info = JavaClass.AttributeInfo.AttrBodyCode(_io, self, self._root)
  else
    self.info = self._io:read_bytes(self.attribute_length)
  end
end

JavaClass.AttributeInfo.property.name_as_str = {}
function JavaClass.AttributeInfo.property.name_as_str:get()
  if self._m_name_as_str ~= nil then
    return self._m_name_as_str
  end

  self._m_name_as_str = self._root.constant_pool[(self.name_index - 1) + 1].cp_info.value
  return self._m_name_as_str
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.3)
JavaClass.AttributeInfo.AttrBodyCode = class.class(KaitaiStruct)

function JavaClass.AttributeInfo.AttrBodyCode:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.AttributeInfo.AttrBodyCode:_read()
  self.max_stack = self._io:read_u2be()
  self.max_locals = self._io:read_u2be()
  self.code_length = self._io:read_u4be()
  self.code = self._io:read_bytes(self.code_length)
  self.exception_table_length = self._io:read_u2be()
  self.exception_table = {}
  for i = 0, self.exception_table_length - 1 do
    self.exception_table[i + 1] = JavaClass.AttributeInfo.AttrBodyCode.ExceptionEntry(self._io, self, self._root)
  end
  self.attributes_count = self._io:read_u2be()
  self.attributes = {}
  for i = 0, self.attributes_count - 1 do
    self.attributes[i + 1] = JavaClass.AttributeInfo(self._io, self, self._root)
  end
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.3)
JavaClass.AttributeInfo.AttrBodyCode.ExceptionEntry = class.class(KaitaiStruct)

function JavaClass.AttributeInfo.AttrBodyCode.ExceptionEntry:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.AttributeInfo.AttrBodyCode.ExceptionEntry:_read()
  self.start_pc = self._io:read_u2be()
  self.end_pc = self._io:read_u2be()
  self.handler_pc = self._io:read_u2be()
  self.catch_type = self._io:read_u2be()
end

JavaClass.AttributeInfo.AttrBodyCode.ExceptionEntry.property.catch_exception = {}
function JavaClass.AttributeInfo.AttrBodyCode.ExceptionEntry.property.catch_exception:get()
  if self._m_catch_exception ~= nil then
    return self._m_catch_exception
  end

  if self.catch_type ~= 0 then
    self._m_catch_exception = self._root.constant_pool[(self.catch_type - 1) + 1]
  end
  return self._m_catch_exception
end

-- 
-- Start of a code region where exception handler is being
-- active, index in code array (inclusive)
-- 
-- End of a code region where exception handler is being
-- active, index in code array (exclusive)
-- 
-- Start of exception handler code, index in code array.
-- 
-- Exception class that this handler catches, index in constant
-- pool, or 0 (catch all exceptions handler, used to implement
-- `finally`).

-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.5)
JavaClass.AttributeInfo.AttrBodyExceptions = class.class(KaitaiStruct)

function JavaClass.AttributeInfo.AttrBodyExceptions:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.AttributeInfo.AttrBodyExceptions:_read()
  self.number_of_exceptions = self._io:read_u2be()
  self.exceptions = {}
  for i = 0, self.number_of_exceptions - 1 do
    self.exceptions[i + 1] = JavaClass.AttributeInfo.AttrBodyExceptions.ExceptionTableEntry(self._io, self, self._root)
  end
end


JavaClass.AttributeInfo.AttrBodyExceptions.ExceptionTableEntry = class.class(KaitaiStruct)

function JavaClass.AttributeInfo.AttrBodyExceptions.ExceptionTableEntry:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.AttributeInfo.AttrBodyExceptions.ExceptionTableEntry:_read()
  self.index = self._io:read_u2be()
end

JavaClass.AttributeInfo.AttrBodyExceptions.ExceptionTableEntry.property.as_info = {}
function JavaClass.AttributeInfo.AttrBodyExceptions.ExceptionTableEntry.property.as_info:get()
  if self._m_as_info ~= nil then
    return self._m_as_info
  end

  self._m_as_info = self._root.constant_pool[(self.index - 1) + 1].cp_info
  return self._m_as_info
end

JavaClass.AttributeInfo.AttrBodyExceptions.ExceptionTableEntry.property.name_as_str = {}
function JavaClass.AttributeInfo.AttrBodyExceptions.ExceptionTableEntry.property.name_as_str:get()
  if self._m_name_as_str ~= nil then
    return self._m_name_as_str
  end

  self._m_name_as_str = self.as_info.name_as_str
  return self._m_name_as_str
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.10)
JavaClass.AttributeInfo.AttrBodySourceFile = class.class(KaitaiStruct)

function JavaClass.AttributeInfo.AttrBodySourceFile:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.AttributeInfo.AttrBodySourceFile:_read()
  self.sourcefile_index = self._io:read_u2be()
end

JavaClass.AttributeInfo.AttrBodySourceFile.property.sourcefile_as_str = {}
function JavaClass.AttributeInfo.AttrBodySourceFile.property.sourcefile_as_str:get()
  if self._m_sourcefile_as_str ~= nil then
    return self._m_sourcefile_as_str
  end

  self._m_sourcefile_as_str = self._root.constant_pool[(self.sourcefile_index - 1) + 1].cp_info.value
  return self._m_sourcefile_as_str
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.12)
JavaClass.AttributeInfo.AttrBodyLineNumberTable = class.class(KaitaiStruct)

function JavaClass.AttributeInfo.AttrBodyLineNumberTable:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.AttributeInfo.AttrBodyLineNumberTable:_read()
  self.line_number_table_length = self._io:read_u2be()
  self.line_number_table = {}
  for i = 0, self.line_number_table_length - 1 do
    self.line_number_table[i + 1] = JavaClass.AttributeInfo.AttrBodyLineNumberTable.LineNumberTableEntry(self._io, self, self._root)
  end
end


JavaClass.AttributeInfo.AttrBodyLineNumberTable.LineNumberTableEntry = class.class(KaitaiStruct)

function JavaClass.AttributeInfo.AttrBodyLineNumberTable.LineNumberTableEntry:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.AttributeInfo.AttrBodyLineNumberTable.LineNumberTableEntry:_read()
  self.start_pc = self._io:read_u2be()
  self.line_number = self._io:read_u2be()
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.2)
JavaClass.MethodRefCpInfo = class.class(KaitaiStruct)

function JavaClass.MethodRefCpInfo:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.MethodRefCpInfo:_read()
  self.class_index = self._io:read_u2be()
  self.name_and_type_index = self._io:read_u2be()
end

JavaClass.MethodRefCpInfo.property.class_as_info = {}
function JavaClass.MethodRefCpInfo.property.class_as_info:get()
  if self._m_class_as_info ~= nil then
    return self._m_class_as_info
  end

  self._m_class_as_info = self._root.constant_pool[(self.class_index - 1) + 1].cp_info
  return self._m_class_as_info
end

JavaClass.MethodRefCpInfo.property.name_and_type_as_info = {}
function JavaClass.MethodRefCpInfo.property.name_and_type_as_info:get()
  if self._m_name_and_type_as_info ~= nil then
    return self._m_name_and_type_as_info
  end

  self._m_name_and_type_as_info = self._root.constant_pool[(self.name_and_type_index - 1) + 1].cp_info
  return self._m_name_and_type_as_info
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5)
JavaClass.FieldInfo = class.class(KaitaiStruct)

function JavaClass.FieldInfo:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.FieldInfo:_read()
  self.access_flags = self._io:read_u2be()
  self.name_index = self._io:read_u2be()
  self.descriptor_index = self._io:read_u2be()
  self.attributes_count = self._io:read_u2be()
  self.attributes = {}
  for i = 0, self.attributes_count - 1 do
    self.attributes[i + 1] = JavaClass.AttributeInfo(self._io, self, self._root)
  end
end

JavaClass.FieldInfo.property.name_as_str = {}
function JavaClass.FieldInfo.property.name_as_str:get()
  if self._m_name_as_str ~= nil then
    return self._m_name_as_str
  end

  self._m_name_as_str = self._root.constant_pool[(self.name_index - 1) + 1].cp_info.value
  return self._m_name_as_str
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.6)
JavaClass.DoubleCpInfo = class.class(KaitaiStruct)

function JavaClass.DoubleCpInfo:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.DoubleCpInfo:_read()
  self.value = self._io:read_f8be()
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.5)
JavaClass.LongCpInfo = class.class(KaitaiStruct)

function JavaClass.LongCpInfo:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.LongCpInfo:_read()
  self.value = self._io:read_u8be()
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.10)
JavaClass.InvokeDynamicCpInfo = class.class(KaitaiStruct)

function JavaClass.InvokeDynamicCpInfo:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.InvokeDynamicCpInfo:_read()
  self.bootstrap_method_attr_index = self._io:read_u2be()
  self.name_and_type_index = self._io:read_u2be()
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.8)
JavaClass.MethodHandleCpInfo = class.class(KaitaiStruct)

JavaClass.MethodHandleCpInfo.ReferenceKindEnum = enum.Enum {
  get_field = 1,
  get_static = 2,
  put_field = 3,
  put_static = 4,
  invoke_virtual = 5,
  invoke_static = 6,
  invoke_special = 7,
  new_invoke_special = 8,
  invoke_interface = 9,
}

function JavaClass.MethodHandleCpInfo:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.MethodHandleCpInfo:_read()
  self.reference_kind = JavaClass.MethodHandleCpInfo.ReferenceKindEnum(self._io:read_u1())
  self.reference_index = self._io:read_u2be()
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.6)
JavaClass.NameAndTypeCpInfo = class.class(KaitaiStruct)

function JavaClass.NameAndTypeCpInfo:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.NameAndTypeCpInfo:_read()
  self.name_index = self._io:read_u2be()
  self.descriptor_index = self._io:read_u2be()
end

JavaClass.NameAndTypeCpInfo.property.name_as_info = {}
function JavaClass.NameAndTypeCpInfo.property.name_as_info:get()
  if self._m_name_as_info ~= nil then
    return self._m_name_as_info
  end

  self._m_name_as_info = self._root.constant_pool[(self.name_index - 1) + 1].cp_info
  return self._m_name_as_info
end

JavaClass.NameAndTypeCpInfo.property.name_as_str = {}
function JavaClass.NameAndTypeCpInfo.property.name_as_str:get()
  if self._m_name_as_str ~= nil then
    return self._m_name_as_str
  end

  self._m_name_as_str = self.name_as_info.value
  return self._m_name_as_str
end

JavaClass.NameAndTypeCpInfo.property.descriptor_as_info = {}
function JavaClass.NameAndTypeCpInfo.property.descriptor_as_info:get()
  if self._m_descriptor_as_info ~= nil then
    return self._m_descriptor_as_info
  end

  self._m_descriptor_as_info = self._root.constant_pool[(self.descriptor_index - 1) + 1].cp_info
  return self._m_descriptor_as_info
end

JavaClass.NameAndTypeCpInfo.property.descriptor_as_str = {}
function JavaClass.NameAndTypeCpInfo.property.descriptor_as_str:get()
  if self._m_descriptor_as_str ~= nil then
    return self._m_descriptor_as_str
  end

  self._m_descriptor_as_str = self.descriptor_as_info.value
  return self._m_descriptor_as_str
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.7)
JavaClass.Utf8CpInfo = class.class(KaitaiStruct)

function JavaClass.Utf8CpInfo:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.Utf8CpInfo:_read()
  self.str_len = self._io:read_u2be()
  self.value = str_decode.decode(self._io:read_bytes(self.str_len), "UTF-8")
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.3)
JavaClass.StringCpInfo = class.class(KaitaiStruct)

function JavaClass.StringCpInfo:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.StringCpInfo:_read()
  self.string_index = self._io:read_u2be()
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.9)
JavaClass.MethodTypeCpInfo = class.class(KaitaiStruct)

function JavaClass.MethodTypeCpInfo:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.MethodTypeCpInfo:_read()
  self.descriptor_index = self._io:read_u2be()
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.2)
JavaClass.InterfaceMethodRefCpInfo = class.class(KaitaiStruct)

function JavaClass.InterfaceMethodRefCpInfo:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.InterfaceMethodRefCpInfo:_read()
  self.class_index = self._io:read_u2be()
  self.name_and_type_index = self._io:read_u2be()
end

JavaClass.InterfaceMethodRefCpInfo.property.class_as_info = {}
function JavaClass.InterfaceMethodRefCpInfo.property.class_as_info:get()
  if self._m_class_as_info ~= nil then
    return self._m_class_as_info
  end

  self._m_class_as_info = self._root.constant_pool[(self.class_index - 1) + 1].cp_info
  return self._m_class_as_info
end

JavaClass.InterfaceMethodRefCpInfo.property.name_and_type_as_info = {}
function JavaClass.InterfaceMethodRefCpInfo.property.name_and_type_as_info:get()
  if self._m_name_and_type_as_info ~= nil then
    return self._m_name_and_type_as_info
  end

  self._m_name_and_type_as_info = self._root.constant_pool[(self.name_and_type_index - 1) + 1].cp_info
  return self._m_name_and_type_as_info
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.1)
JavaClass.ClassCpInfo = class.class(KaitaiStruct)

function JavaClass.ClassCpInfo:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.ClassCpInfo:_read()
  self.name_index = self._io:read_u2be()
end

JavaClass.ClassCpInfo.property.name_as_info = {}
function JavaClass.ClassCpInfo.property.name_as_info:get()
  if self._m_name_as_info ~= nil then
    return self._m_name_as_info
  end

  self._m_name_as_info = self._root.constant_pool[(self.name_index - 1) + 1].cp_info
  return self._m_name_as_info
end

JavaClass.ClassCpInfo.property.name_as_str = {}
function JavaClass.ClassCpInfo.property.name_as_str:get()
  if self._m_name_as_str ~= nil then
    return self._m_name_as_str
  end

  self._m_name_as_str = self.name_as_info.value
  return self._m_name_as_str
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4)
JavaClass.ConstantPoolEntry = class.class(KaitaiStruct)

JavaClass.ConstantPoolEntry.TagEnum = enum.Enum {
  utf8 = 1,
  integer = 3,
  float = 4,
  long = 5,
  double = 6,
  class_type = 7,
  string = 8,
  field_ref = 9,
  method_ref = 10,
  interface_method_ref = 11,
  name_and_type = 12,
  method_handle = 15,
  method_type = 16,
  invoke_dynamic = 18,
}

function JavaClass.ConstantPoolEntry:_init(is_prev_two_entries, io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self.is_prev_two_entries = is_prev_two_entries
  self:_read()
end

function JavaClass.ConstantPoolEntry:_read()
  if not(self.is_prev_two_entries) then
    self.tag = JavaClass.ConstantPoolEntry.TagEnum(self._io:read_u1())
  end
  if not(self.is_prev_two_entries) then
    local _on = self.tag
    if _on == JavaClass.ConstantPoolEntry.TagEnum.interface_method_ref then
      self.cp_info = JavaClass.InterfaceMethodRefCpInfo(self._io, self, self._root)
    elseif _on == JavaClass.ConstantPoolEntry.TagEnum.class_type then
      self.cp_info = JavaClass.ClassCpInfo(self._io, self, self._root)
    elseif _on == JavaClass.ConstantPoolEntry.TagEnum.utf8 then
      self.cp_info = JavaClass.Utf8CpInfo(self._io, self, self._root)
    elseif _on == JavaClass.ConstantPoolEntry.TagEnum.method_type then
      self.cp_info = JavaClass.MethodTypeCpInfo(self._io, self, self._root)
    elseif _on == JavaClass.ConstantPoolEntry.TagEnum.integer then
      self.cp_info = JavaClass.IntegerCpInfo(self._io, self, self._root)
    elseif _on == JavaClass.ConstantPoolEntry.TagEnum.string then
      self.cp_info = JavaClass.StringCpInfo(self._io, self, self._root)
    elseif _on == JavaClass.ConstantPoolEntry.TagEnum.float then
      self.cp_info = JavaClass.FloatCpInfo(self._io, self, self._root)
    elseif _on == JavaClass.ConstantPoolEntry.TagEnum.long then
      self.cp_info = JavaClass.LongCpInfo(self._io, self, self._root)
    elseif _on == JavaClass.ConstantPoolEntry.TagEnum.method_ref then
      self.cp_info = JavaClass.MethodRefCpInfo(self._io, self, self._root)
    elseif _on == JavaClass.ConstantPoolEntry.TagEnum.double then
      self.cp_info = JavaClass.DoubleCpInfo(self._io, self, self._root)
    elseif _on == JavaClass.ConstantPoolEntry.TagEnum.invoke_dynamic then
      self.cp_info = JavaClass.InvokeDynamicCpInfo(self._io, self, self._root)
    elseif _on == JavaClass.ConstantPoolEntry.TagEnum.field_ref then
      self.cp_info = JavaClass.FieldRefCpInfo(self._io, self, self._root)
    elseif _on == JavaClass.ConstantPoolEntry.TagEnum.method_handle then
      self.cp_info = JavaClass.MethodHandleCpInfo(self._io, self, self._root)
    elseif _on == JavaClass.ConstantPoolEntry.TagEnum.name_and_type then
      self.cp_info = JavaClass.NameAndTypeCpInfo(self._io, self, self._root)
    end
  end
end

JavaClass.ConstantPoolEntry.property.is_two_entries = {}
function JavaClass.ConstantPoolEntry.property.is_two_entries:get()
  if self._m_is_two_entries ~= nil then
    return self._m_is_two_entries
  end

  self._m_is_two_entries =  ((self.tag == JavaClass.ConstantPoolEntry.TagEnum.long) or (self.tag == JavaClass.ConstantPoolEntry.TagEnum.double)) 
  return self._m_is_two_entries
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6)
JavaClass.MethodInfo = class.class(KaitaiStruct)

function JavaClass.MethodInfo:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.MethodInfo:_read()
  self.access_flags = self._io:read_u2be()
  self.name_index = self._io:read_u2be()
  self.descriptor_index = self._io:read_u2be()
  self.attributes_count = self._io:read_u2be()
  self.attributes = {}
  for i = 0, self.attributes_count - 1 do
    self.attributes[i + 1] = JavaClass.AttributeInfo(self._io, self, self._root)
  end
end

JavaClass.MethodInfo.property.name_as_str = {}
function JavaClass.MethodInfo.property.name_as_str:get()
  if self._m_name_as_str ~= nil then
    return self._m_name_as_str
  end

  self._m_name_as_str = self._root.constant_pool[(self.name_index - 1) + 1].cp_info.value
  return self._m_name_as_str
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.4)
JavaClass.IntegerCpInfo = class.class(KaitaiStruct)

function JavaClass.IntegerCpInfo:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.IntegerCpInfo:_read()
  self.value = self._io:read_u4be()
end


-- 
-- See also: Source (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.2)
JavaClass.FieldRefCpInfo = class.class(KaitaiStruct)

function JavaClass.FieldRefCpInfo:_init(io, parent, root)
  KaitaiStruct._init(self, io)
  self._parent = parent
  self._root = root or self
  self:_read()
end

function JavaClass.FieldRefCpInfo:_read()
  self.class_index = self._io:read_u2be()
  self.name_and_type_index = self._io:read_u2be()
end

JavaClass.FieldRefCpInfo.property.class_as_info = {}
function JavaClass.FieldRefCpInfo.property.class_as_info:get()
  if self._m_class_as_info ~= nil then
    return self._m_class_as_info
  end

  self._m_class_as_info = self._root.constant_pool[(self.class_index - 1) + 1].cp_info
  return self._m_class_as_info
end

JavaClass.FieldRefCpInfo.property.name_and_type_as_info = {}
function JavaClass.FieldRefCpInfo.property.name_and_type_as_info:get()
  if self._m_name_and_type_as_info ~= nil then
    return self._m_name_and_type_as_info
  end

  self._m_name_and_type_as_info = self._root.constant_pool[(self.name_and_type_index - 1) + 1].cp_info
  return self._m_name_and_type_as_info
end