class JvmBytecode::ClassFile

Constants

ACCESS_FLAGS
MAGIC_NUMBER

Public Class Methods

decode(io) click to toggle source
# File lib/jvm_bytecode/class_file.rb, line 18
def self.decode(io)
  new.tap { |cf| cf.decode(io) }
end
new(&block) click to toggle source
# File lib/jvm_bytecode/class_file.rb, line 22
def initialize(&block)
  @cp = ConstantPool.new

  @minor_ver = 0
  @major_ver = 52

  @this_class = nil
  @super_class = nil

  @interfaces = []
  @fields = []
  @methods = []
  @attributes = []

  self.instance_eval(&block) if block_given?
end

Public Instance Methods

add_method(m) click to toggle source
# File lib/jvm_bytecode/class_file.rb, line 63
def add_method(m)
  @methods.push(m).last
end
bytecode() click to toggle source
# File lib/jvm_bytecode/class_file.rb, line 77
def bytecode
  version    = [@minor_ver, @major_ver].pack('S>*')
  classes    = [access_flag, @this_class, @super_class].pack('S>*')
  interfaces = ([@interfaces.length] + @interfaces).pack("S>*")
  fields     = @fields.join_bytecodes
  methods    = @methods.join_bytecodes
  attributes = @attributes.join_bytecodes

  MAGIC_NUMBER + version + @cp.bytecode + classes + interfaces + fields + methods + attributes
end
constant_pool(&block) click to toggle source
# File lib/jvm_bytecode/class_file.rb, line 39
def constant_pool(&block)
  @cp.tap { |cp| cp.instance_eval(&block) if block_given? }
end
decode(io) click to toggle source
# File lib/jvm_bytecode/class_file.rb, line 88
def decode(io)
  raise Errors::DecodeError, 'Not class file' if io.read(4) != MAGIC_NUMBER

  @minor_ver, @major_ver = io.read(4).unpack('S>2')

  @cp.decode(io)

  acc_flag, @this_class, @super_class = io.read(6).unpack('S>3')
  set_access_flag(acc_flag)

  if_count = io.read(2).unpack('S>').first
  @interfaces = io.read(if_count * 2).unpack("S>#{if_count}")

  @fields = Field.decode_serial(@cp, io)
  @methods = Method.decode_serial(@cp, io)
end
major_version(v) click to toggle source
# File lib/jvm_bytecode/class_file.rb, line 47
def major_version(v)
  @major_ver = v
end
method_definition(&block) click to toggle source
# File lib/jvm_bytecode/class_file.rb, line 67
def method_definition(&block)
  add_method(new_method).tap { |m| m.instance_eval(&block) if block_given?}
end
minor_version(v) click to toggle source
# File lib/jvm_bytecode/class_file.rb, line 43
def minor_version(v)
  @minor_ver = v
end
new_method() click to toggle source
# File lib/jvm_bytecode/class_file.rb, line 59
def new_method
  Method.new(@cp)
end
source_file(filename) click to toggle source
# File lib/jvm_bytecode/class_file.rb, line 71
def source_file(filename)
  @attributes << Attributes::SourceFile.new(@cp).tap do |a|
    a.filename(filename)
  end
end
super_class(name) click to toggle source
# File lib/jvm_bytecode/class_file.rb, line 55
def super_class(name)
  @super_class = @cp.class_index(name)
end
this_class(name) click to toggle source
# File lib/jvm_bytecode/class_file.rb, line 51
def this_class(name)
  @this_class = @cp.class_index(name)
end
to_hash() click to toggle source
# File lib/jvm_bytecode/class_file.rb, line 105
def to_hash
  {
    minor_version: @minor_ver,
    major_version: @major_ver,
    constant_pool: @cp.to_hash,
    access_flag: readable_access_flag,
    this_class: @this_class,
    super_class: @super_class,
    methods: @methods.map(&:to_hash)
  }
end