Class Ruva::VM::Class
In: lib/ruva/class.rb
lib/ruva/class_loader.rb
Parent: Object

A Class holds the internal runtime representation of a resolved Java class (see also: Ruva::VM::Class::Reader::UnresolvedClass). Instances of this class are normally produced by the Ruva::VM::ClassLoader, although this class is a visitor - it can be passed to the accept method of an UnresolvedClass instance.

INSTANCES MUST NOT BE SHARED BETWEEN VMs!

Methods

Included Modules

AccessHelpers Helpers

Classes and Modules

Module Ruva::VM::Class::AccessHelpers
Module Ruva::VM::Class::Helpers
Class Ruva::VM::Class::Annotation
Class Ruva::VM::Class::Exception
Class Ruva::VM::Class::Field
Class Ruva::VM::Class::InnerClass
Class Ruva::VM::Class::Method
Class Ruva::VM::Class::Reader

Constants

ACC_PUBLIC = 0x0001
ACC_PRIVATE = 0x0002
ACC_PROTECTED = 0x0004
ACC_FINAL = 0x0010
ACC_SUPER = 0x0020
ACC_INTERFACE = 0x0200
ACC_ABSTRACT = 0x0400
ACC_SYNTHETIC = 0x1000
ACC_ANNOTATION = 0x2000
ACC_ENUM = 0x4000
HUMAN_DESC_RE = /^(\[)?(B|C|D|F|I|J|L|S|V|Z)(?:([^;]+)?)/
AnnotationEnum = Struct.new :name, :desc, :value
LineNumber = Struct.new :line, :start_pc
LocalVariable = Struct.new :name, :desc, :signature, :start_ofs, :end_ofs, :index
Exception = Struct.new :start_pc, :end_pc, :handler_pc
InnerClass = Struct.new :access, :name, :outer, :inner
OuterClass = Struct.new :owner, :name, :desc

External Aliases

initialized -> initialized?
linked -> linked?
inspect -> full_inspect

Attributes

access  [RW] 
annotations  [RW] 
attrs  [RW] 
field_lookup  [RW] 
fields  [RW] 
initialized  [RW]  Has class been initialized? (<clinit> run)
inner_classes  [RW] 
interfaces  [RW] 
linked  [RW]  Has class been linked into the runtime?
method_lookup  [RW] 
methods  [RW] 
name  [RW] 
outer_class  [RW] 
pool  [RW] 
signature  [RW] 
source  [RW] 
super_name  [RW] 
ver_maj  [RW] 
ver_min  [RW] 

Public Class methods

[Source]

     # File lib/ruva/class.rb, line 101
101:         def human_access_class(e)
102:           (basic_human_access(e) + "#{'final ' if e.final?}#{'abstract ' if e.abstract?}" +                               
103:                                if e.interface?
104:                                  'interface'
105:                                elsif e.annotation?
106:                                  '@interface'
107:                                elsif e.enum?
108:                                  'enum'
109:                                else
110:                                  'class'
111:                                end)
112:         end

[Source]

     # File lib/ruva/class.rb, line 114
114:         def human_access_field(e)
115:           (basic_human_access(e) + "#{'volatile ' if e.volatile?}#{'transient ' if e.transient?}")        
116:         end

[Source]

     # File lib/ruva/class.rb, line 118
118:         def human_access_method(e)
119:           (basic_human_access(e) + "#{'final ' if e.final?}#{'abstract ' if e.abstract?}#{'native ' if e.native?}" + 
120:                                 "#{'synchronized ' if e.synchronized?}#{'bridge ' if e.bridge?}" +
121:                                 "#{'varargs ' if e.varargs?}#{'strictfp ' if e.strict?}#{'synthetic ' if e.synthetic?}")
122:         end

Maps an array of descriptors to human-readable format.

[Source]

    # File lib/ruva/class.rb, line 97
97:         def human_argdescs(argdescs)
98:           argdescs.map { |e| human_desc(e) }
99:         end

Helper method that gives a human-readable version of a type descriptor

[Source]

    # File lib/ruva/class.rb, line 59
59:         def human_desc(desc)
60:           if desc =~ HUMAN_DESC_RE
61:             ret = case $2
62:             when 'L'
63:               $3.tr('/', '.')
64:             when 'B'
65:               'byte'
66:             when 'C'
67:               'char'
68:             when 'D'
69:               'double'
70:             when 'F'
71:               'float'
72:             when 'I'
73:               'int'
74:             when 'J'
75:               'long'
76:             when 'S'
77:               'short'
78:             when 'V'
79:               'void'
80:             when 'Z'
81:               'boolean'            
82:             else
83:               desc  # invalid descriptor
84:             end
85:             
86:             if $1
87:               ret + '[]'
88:             else
89:               ret
90:             end
91:           else
92:             desc
93:           end
94:         end

[Source]

     # File lib/ruva/class.rb, line 438
438:       def initialize(ver_maj = nil, ver_min = nil, access = nil, name = nil, signature = nil, super_name = nil, interfaces = [])
439:         self.ver_maj, self.ver_min, self.access, self.name, self.signature, self.super_name, self.interfaces = 
440:           ver_maj, ver_min, access, name, signature, super_name, interfaces
441:           
442:         # start the runtime pool with the class reference itself.
443:         # 'proper', and stops us having to subtract one from all the cpool indices.
444:         @annotations, @fields, @methods, @attrs, @inner_classes, @pool = [], [], [], [], [], [self]
445:         @field_lookup, @method_lookup = {}, {}
446:         @initialized = false
447:         @linked = false
448:         @natives = nil
449:       end

Obtains the class of the specified primitive type

[Source]

    # File lib/ruva/class.rb, line 29
29:         def of_primitive(type)
30:           case type
31:           when 'B'
32:             @byte_class ||= new(49, 0, ACC_PUBLIC | ACC_FINAL, 'byte', 'B', nil)
33:           when 'C'
34:             @char_class ||= new(49, 0, ACC_PUBLIC | ACC_FINAL, 'char', 'C', nil)
35:           when 'D'
36:             @double_class ||= new(49, 0, ACC_PUBLIC | ACC_FINAL, 'double', 'D', nil)
37:           when 'F'
38:             @float_class ||= new(49, 0, ACC_PUBLIC | ACC_FINAL, 'float', 'F', nil)
39:           when 'I'
40:             @int_class ||= new(49, 0, ACC_PUBLIC | ACC_FINAL, 'int', 'I', nil)
41:           when 'J'
42:             @long_class ||= new(49, 0, ACC_PUBLIC | ACC_FINAL, 'long', 'J', nil)
43:           when 'S'
44:             @short_class ||= new(49, 0, ACC_PUBLIC | ACC_FINAL, 'short', 'S', nil)
45:           when 'V'
46:             @void_class ||= new(49, 0, ACC_PUBLIC | ACC_FINAL, 'void', 'V', nil)
47:           when 'Z'
48:             @boolean_class ||= new(49, 0, ACC_PUBLIC | ACC_FINAL, 'boolean', 'Z', nil)
49:           else
50:             raise VM::TypeError, "Invalid primitive type #{type}"
51:           end        
52:         end

Public Instance methods

[Source]

     # File lib/ruva/class.rb, line 539
539:       def ==(other)
540:         other.is_a?(self.class) && name == other.name      
541:       end
eql?(other)

Alias for #==

[Source]

     # File lib/ruva/class.rb, line 545
545:       def hash
546:         name.hash
547:       end

[Source]

     # File lib/ruva/class.rb, line 555
555:       def inspect
556:         "#<#{to_s}>"
557:       end

[Source]

     # File lib/ruva/class.rb, line 463
463:       def natives(nmod)
464:         @natives ||= begin
465:           name.split('/').map { |e| e[0,1].upcase + e[1..-1] }.inject(nmod) { |mod, sm|
466:             mod.const_get(sm)
467:           }
468:         rescue NameError
469:           nil
470:         end
471:       end

[Source]

     # File lib/ruva/class.rb, line 459
459:       def natives=(native_mod)
460:         @natives = native_mod
461:       end

[Source]

     # File lib/ruva/class.rb, line 549
549:       def to_s
550:         name
551:       end

CLASSVISITOR

[Source]

     # File lib/ruva/class.rb, line 452
452:       def visit(ver_maj, ver_min, access, name, signature, super_name, interfaces)
453:         initialize(ver_maj, ver_min, access, name, signature, super_name, interfaces)
454:       end

Visit an annotation. Should return an Annotation visitor to suit.

[Source]

     # File lib/ruva/class.rb, line 477
477:       def visit_annotation(desc, visible)
478:         annotations << a = Annotation.new(desc, visible)
479:         a
480:       end

Visit a non=standard attribute

[Source]

     # File lib/ruva/class.rb, line 483
483:       def visit_attribute(attr)
484:         attrs << attr
485:       end

Visit a constant pool entry.

[Source]

     # File lib/ruva/class.rb, line 488
488:       def visit_cpool_entry(orig_pool, data, type)
489:         
490:         case type
491:         when :class
492:           pool << VM::Types::ConstClassRef.new(nil, {}, orig_pool[data[:name_index] - 1].data)
493:         when :field, :method, :if_method
494:           pool << { :class => orig_pool[orig_pool[data[:class_index] - 1].data[:name_index] - 1].data, 
495:                     :name  => orig_pool[orig_pool[data[:name_type_index] - 1].data[:name_index] - 1].data,
496:                     :desc  => orig_pool[orig_pool[data[:name_type_index] - 1].data[:desc_index] - 1].data }
497:         when :string
498:           pool << VM::Types::ConstStringRef.new(nil, {}, orig_pool[data[:string_index] - 1].data)
499:         when :int, :long, :float, :double, :utf8
500:           # TODO : don't add stuff we don't need (e.g. utf8s we already resolved out).
501:           pool << data
502:         when :name_type
503:           # not needed, we resolved 'em out. Add a nil to keep the indexes right.
504:           pool << nil
505:         when :empty
506:           # internal type, signifies we need a space in the pool following a cat2 type
507:           pool << nil
508:         end
509:       end

[Source]

     # File lib/ruva/class.rb, line 473
473:       def visit_end
474:       end

should return a FieldVisitor

[Source]

     # File lib/ruva/class.rb, line 512
512:       def visit_field(access, name, desc, signature, value)
513:         fields << f = Field.new(access, name, desc, signature, value)
514:         field_lookup[name+desc] = fields.length - 1
515:         f
516:       end

visit an inner class

[Source]

     # File lib/ruva/class.rb, line 526
526:       def visit_inner_class(access, name, outer, inner)
527:         self.inner_class = InnerClass.new(access, name, outer, inner)
528:       end

should return a MethodVisitor

[Source]

     # File lib/ruva/class.rb, line 519
519:       def visit_method(access, name, desc, signature, throws)
520:         methods << m = Method.new(self, access, name, desc, signature, throws)
521:         method_lookup[name+desc] = methods.length - 1
522:         m
523:       end

visit an enclosing class

[Source]

     # File lib/ruva/class.rb, line 531
531:       def visit_outer_class(owner, name, desc)
532:         self.outer_class = OuterClass.new(owner, name, desc)
533:       end

[Source]

     # File lib/ruva/class.rb, line 535
535:       def visit_source(source, debug)
536:         self.source = source
537:       end

[Validate]