harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gshiman...@apache.org
Subject svn commit: r490202 - in /harmony/enhanced/drlvm/trunk/vm/vmcore: include/ src/class_support/ src/init/ src/kernel_classes/native/ src/reflection/
Date Tue, 26 Dec 2006 00:07:26 GMT
Author: gshimansky
Date: Mon Dec 25 16:07:25 2006
New Revision: 490202

URL: http://svn.apache.org/viewvc?view=rev&rev=490202
Log:
Applied HARMONY-2872 [drlvm][classloader] Improved class file format parser

Tests passed on Ubuntu6 x86, WindowsXP x86 and SuSE9 x86_64


Modified:
    harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/include/annotations.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/include/class_member.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/C_Interface.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class_File_Loader.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Resolve.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/parse_arguments.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMGenericsAndAnnotations.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/reflection/annotations.cpp

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h?view=diff&rev=490202&r1=490201&r2=490202
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h Mon Dec 25 16:07:25 2006
@@ -161,7 +161,7 @@
 enum ConstPoolTags {
     /** pointer to the tags array.*/
     CONSTANT_Tags               = 0,
-    /** The rest of tag values are taken from
+    /** The next 11 tag values are taken from
      * <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/ClassFileFormat-Java5.pdf">
      * The Java Virtual Machine Specification, Chapter 4</a>, <i>The Constant
      * Pool</i> section.*/
@@ -176,6 +176,9 @@
     CONSTANT_Methodref          = 10,
     CONSTANT_InterfaceMethodref = 11,
     CONSTANT_NameAndType        = 12,
+    CONSTANT_Last               = CONSTANT_NameAndType,
+    /** used to mark second entry of Long and Double*/
+    CONSTANT_UnusedEntry        = CONSTANT_Last + 1,    
 };
 
 
@@ -1001,6 +1004,9 @@
     // annotations for this class
     AnnotationTable* m_annotations;
 
+    //invisible annotations for this class
+    AnnotationTable* m_invisible_annotations;
+ 
     // thread, which currently executes <clinit>
     VM_thread* m_initializing_thread;
 
@@ -1340,7 +1346,11 @@
     /** Gets a collection of annotations.
      * @return A collection of annotations.*/
     AnnotationTable* get_annotations() const { return m_annotations; }
-
+    /** Gets a collection of invisible annotations.
+     * @return A collection of invisible annotations.*/
+    AnnotationTable* get_invisible_annotations() const {
+        return m_invisible_annotations;
+    }
     /** Gets a class instance size.
      * @return A size of the allocated instance in bytes.*/
     unsigned int get_allocated_size() const { return m_allocated_size; }

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/annotations.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/annotations.h?view=diff&rev=490202&r1=490201&r2=490202
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/annotations.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/annotations.h Mon Dec 25 16:07:25 2006
@@ -29,10 +29,11 @@
 struct Annotation;
 struct AnnotationValue;
 
-// Returns array of declared annotations.
+// Returns array of declared visible annotations
+// and in case -Xinvisible command line flag is set also returns array of invisible annotations.
 // Returns zero-sized array if there are no annotations.
 // May raise an exception, in this case returns null.
-jobjectArray get_annotations(JNIEnv* jenv, AnnotationTable* table, Class* clss);
+jobjectArray get_annotations(JNIEnv* jenv, AnnotationTable* table, AnnotationTable *inv_table, Class* clss);
 
 // Returns resolved annotation or null if resolution failed.
 // If the cause parameter is not null, resolution error is assigned to it for upstream processing;

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/class_member.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/class_member.h?view=diff&rev=490202&r1=490201&r2=490202
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/class_member.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/class_member.h Mon Dec 25 16:07:25 2006
@@ -86,6 +86,9 @@
     String *get_signature() const {return _signature;}
 
     AnnotationTable* get_declared_annotations() const {return _annotations;}
+    AnnotationTable* get_declared_invisible_annotations() const {
+        return _invisible_annotations;
+    }
 
     friend void assign_offsets_to_class_fields(Class *);
     friend void add_new_fake_method(Class *clss, Class *example, unsigned *next);
@@ -109,6 +112,7 @@
 #endif
         _synthetic = _deprecated = false;
         _annotations = NULL;
+        _invisible_annotations = NULL;
         _signature = NULL;
     }
 
@@ -122,6 +126,7 @@
     bool _synthetic;
     bool _deprecated;
     AnnotationTable* _annotations;
+    AnnotationTable* _invisible_annotations;
 
     uint16 _access_flags;
     String* _name;
@@ -208,7 +213,7 @@
     unsigned is_transient() {return (_access_flags&ACC_TRANSIENT);} 
     bool is_enum()          {return (_access_flags&ACC_ENUM)?true:false;} 
 
-    bool parse(Class* clss, ByteReader& cfs);
+    bool parse(Global_Env& env, Class* clss, ByteReader& cfs);
 
     unsigned calculate_size();
 
@@ -647,11 +652,22 @@
     AnnotationTable * get_param_annotations(unsigned index) {
         return index < _num_param_annotations ? _param_annotations[index] : NULL;
     }
+    unsigned get_num_invisible_param_annotations() {
+        return _num_invisible_param_annotations;
+    }
+    AnnotationTable * get_invisible_param_annotations(unsigned index) {
+        return index < _num_invisible_param_annotations ?
+                        _invisible_param_annotations[index] : NULL;
+    }
+    
     AnnotationValue * get_default_value() {return _default_value; }
 
 private:
     uint8 _num_param_annotations;
     AnnotationTable ** _param_annotations;
+    uint8 _num_invisible_param_annotations;
+    AnnotationTable ** _invisible_param_annotations; 
+    
     AnnotationValue * _default_value;
 
     unsigned _index;                // index in method table

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h?view=diff&rev=490202&r1=490201&r2=490202
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h Mon Dec 25 16:07:25 2006
@@ -74,7 +74,8 @@
     size_t system_page_size;        // system page size according to use_large_pages value
     bool verify_all;                // psrebriy 20050815 Verify all classes including loaded by bootstrap class loader
     bool pin_interned_strings;      // if true, interned strings are never moved
-
+    bool retain_invisible_annotations; // retain InvisibleAnnotation and InvisibleParameterAnnotation
+    
     Lock_Manager *p_jit_a_method_lock;
     Lock_Manager *p_vtable_patch_lock;
     Lock_Manager *p_meth_addr_table_lock;

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/C_Interface.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/C_Interface.cpp?view=diff&rev=490202&r1=490201&r2=490202
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/C_Interface.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/C_Interface.cpp Mon Dec 25 16:07:25 2006
@@ -843,6 +843,14 @@
     case CONSTANT_Class:
         jt = JAVA_TYPE_CLASS;
         break;
+    case CONSTANT_UnusedEntry:
+        if(cp.get_tag(index - 1) == CONSTANT_Double) {
+            jt = JAVA_TYPE_DOUBLE;
+            break;
+        } else if(cp.get_tag(index - 1) == CONSTANT_Long) {
+            jt = JAVA_TYPE_LONG;
+            break;
+        }
     default:
         DIE("non-constant type is requested from constant pool : " << cp.get_tag(index));
     }

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp?view=diff&rev=490202&r1=490201&r2=490202
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp Mon Dec 25 16:07:25 2006
@@ -627,7 +627,9 @@
     _line_number_table = NULL;
     _local_vars_table = NULL;
     _num_param_annotations = 0;
+    _num_invisible_param_annotations = 0;    
     _param_annotations = NULL;
+    _invisible_param_annotations = NULL;    
     _default_value = NULL;
 
     pending_breakpoints = 0;

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class_File_Loader.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class_File_Loader.cpp?view=diff&rev=490202&r1=490201&r2=490202
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class_File_Loader.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class_File_Loader.cpp Mon Dec 25 16:07:25 2006
@@ -48,15 +48,13 @@
 
 //
 // TODO list:
-//
-//    (1) verify correctness of Method access_flags for different class file versions
-//    (2) verify correctness of Field access_flags  for different class file versions
-//    (3) verify Class access_flags for different class file versions
-//    (4) check that Signature of attribute LocalVariableTypeTable of Code attribute is valid
-//    (5) implement functionality of RuntimeInvisibleAnnotations
-//        and RuntimeInvisibleParameterAnnotations, not just skip them
-//    (6) check Signature attribute, not only parse it
-//
+//  (1) Make macro valid_cpi function static bool, add ClassFormatError reporting to valid_cpi,
+//  replace functions is_valid_index and is_<tag> by valid_cpi.
+//  (2) Funtion parse_annotation_value doesn't report ClassFormatError in case
+//  const_inx is invalid.        
+//  (3) Implement field and method name check for 45 and lower versions of class file.
+
+//    
 
 #define REPORT_FAILED_CLASS_FORMAT(klass, msg)   \
     {                                                               \
@@ -69,8 +67,6 @@
     (clss->get_constant_pool().is_valid_index(idx) \
     && clss->get_constant_pool().get_tag(idx) == type)
 
-
-
 static String* cp_check_utf8(ConstantPool& cp, unsigned utf8_index)
 {
     if(!cp.is_valid_index(utf8_index) || !cp.is_utf8(utf8_index)) {
@@ -542,13 +538,30 @@
     return read_len;
 }
 
+static uint32 parse_parameter_annotations(AnnotationTable *** table,
+                                        uint8 num_annotations,
+                                        ByteReader& cfs, Class* clss)
+{
+    *table = (AnnotationTable**)clss->get_class_loader()->Alloc(
+        num_annotations * sizeof (AnnotationTable*));
+    //FIXME: verav should throw OOM
+    uint32 len = 0;
+    for (unsigned i = 0; i < num_annotations; i++)
+    {
+        uint32 next_len = parse_annotation_table(*table + i, cfs, clss);
+        if(next_len == 0)
+            return 0;
+        len += next_len;
+    }
+    return len;
+}
+
 void* Class_Member::Alloc(size_t size) {
     ClassLoader* cl = get_class()->get_class_loader();
     assert(cl);
     return cl->Alloc(size);
 }
 
-
 bool Class_Member::parse(Class* clss, ByteReader &cfs)
 {
     if (!cfs.parse_u2_be(&_access_flags)) {
@@ -596,7 +609,7 @@
 // further constrained so that, with the exception of the special method names (§3.9)
 // <init> and <clinit>, they must not contain the characters ’<’ or ’>’.
 static inline bool
-check_field_name(const char *name, unsigned len)
+check_field_name(const char *name, unsigned len, bool old_version)
 {
     for (unsigned i = 0; i < len; i++) {
         switch(name[i]){
@@ -611,7 +624,7 @@
 }
 
 static inline bool
-check_method_name(const char *name, unsigned len)
+check_method_name(const char *name, unsigned len, bool version)
 {
     for (unsigned i = 0; i < len; i++) {
         switch(name[i]){
@@ -666,7 +679,7 @@
                     return false;
                 }
                 if(*iterator == '/') {
-                    if(!check_field_name(descriptor, id_len))
+                    if(!check_field_name(descriptor, id_len, false))
                         return false;
                     id_len = 0;
                     descriptor = iterator + 1;
@@ -674,7 +687,7 @@
                     id_len++;
                 }
             }
-            if(!check_field_name(descriptor, id_len))
+            if(!check_field_name(descriptor, id_len, false))
                 return false;
             *next = iterator + 1;
             return true;
@@ -696,16 +709,21 @@
     // DIE( "unreachable code!" ); // exclude remark #111: statement is unreachable
 }
 
-bool Field::parse(Class *clss, ByteReader &cfs)
+//checks of field and method name depend on class version 
+static const uint16 JAVA5_CLASS_FILE_VERSION = 49;
+
+bool Field::parse(Global_Env& env, Class *clss, ByteReader &cfs )
 {
     if(!Class_Member::parse(clss, cfs))
         return false;
 
-    if(!check_field_name(_name->bytes, _name->len)) {
+    if(env.verify_all
+            && !check_field_name(_name->bytes, _name->len,
+                   clss->get_version() < JAVA5_CLASS_FILE_VERSION)) 
+    {
         REPORT_FAILED_CLASS_FORMAT(clss, "illegal field name : " << _name->bytes);
         return false;
     }
-
     // check field descriptor
     //See specification 4.4.2 about field descriptors.
     const char* next;
@@ -716,24 +734,32 @@
 
     // check fields access flags
     //See specification 4.6 about access flags
-    if( clss->is_interface() ) {
+    if(clss->is_interface()) {
         // check interface fields access flags
         if(!(is_public() && is_static() && is_final())){
             REPORT_FAILED_CLASS_FORMAT(clss, "interface field " << get_name()->bytes
-                << " does not have one of ACC_PUBLIC, ACC_STATIC, or ACC_FINAL access flags set");
+                << " has invalid combination of access flags: "
+                << "0x" << std::hex << _access_flags);
             return false;
         }
         if(_access_flags & ~(ACC_FINAL | ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC)){
             REPORT_FAILED_CLASS_FORMAT(clss, "interface field " << get_name()->bytes
-                << " has illegal access flags set : " << _access_flags); //FIXME to literal form
+                << " has invalid combination of access flags: "
+                << "0x"<< std::hex << _access_flags);
             return false;
         }
+        if(clss->get_version() < JAVA5_CLASS_FILE_VERSION) {
+            //for class file version lower than 49 these two flags should be set to zero
+            //See specification 4.5 Fields, for 1.4 Java.
+            _access_flags &= ~(ACC_SYNTHETIC | ACC_ENUM);
+        }
     } else if((is_public() && is_protected()
         || is_protected() && is_private()
         || is_public() && is_private())
         || (is_final() && is_volatile())) {
         REPORT_FAILED_CLASS_FORMAT(clss, " field " << get_name()->bytes
-            << " has invalid combination of access flags : " << _access_flags); //FIXME to literal form
+            << " has invalid combination of access flags: "
+            << "0x" << std::hex << _access_flags);
         return false;
     }
 
@@ -875,6 +901,11 @@
                             const_value.string = cp.get_string(_const_value_index);
                             break;
                         }
+                    case CONSTANT_UnusedEntry:
+                        {
+                            //do nothing here
+                            break;
+                        }
                     default:
                         {
                             REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss,
@@ -935,6 +966,8 @@
                 }
 
                 uint32 read_len = parse_annotation_table(&_annotations, cfs, clss);
+                if(read_len == 0)
+                    return false;
                 if (attr_len != read_len) {
                     REPORT_FAILED_CLASS_FORMAT(clss,
                         "error parsing Annotations attribute"
@@ -947,15 +980,30 @@
 
         case ATTR_RuntimeInvisibleAnnotations:
             {
+                // Each field_info structure may contain at most one RuntimeInvisibleAnnotations attribute.
                 if(++numRuntimeInvisibleAnnotations > 1) {
                     REPORT_FAILED_CLASS_FORMAT(clss,
                         "more than one RuntimeVisibleAnnotations attribute");
                     return false;
                 }
-                if(!cfs.skip(attr_len)) {
-                    REPORT_FAILED_CLASS_FORMAT(clss,
-                        "failed to skip RuntimeInvisibleAnnotations attribute");
-                    return false;
+                if(env.retain_invisible_annotations) {
+                    uint32 read_len =
+                        parse_annotation_table(&_invisible_annotations, cfs, clss);
+                    if(read_len == 0)
+                        return false;
+                    if(attr_len != read_len) {
+                        REPORT_FAILED_CLASS_FORMAT(clss,
+                            "error parsing RuntimeInvisibleAnnotations attribute"
+                            << "; declared length " << attr_len
+                            << " does not match actual " << read_len);
+                        return false;
+                    }
+                } else {
+                    if(!cfs.skip(attr_len)) {
+                        REPORT_FAILED_CLASS_FORMAT(clss,
+                            "failed to skip RuntimeInvisibleAnnotations attribute");
+                        return false;
+                    }
                 }
             }
             break;
@@ -1217,7 +1265,8 @@
             return false;
         }
 
-        if(!check_field_name(name->bytes, name->len))
+        if(!check_field_name(name->bytes, name->len,
+                _class->get_version() < JAVA5_CLASS_FILE_VERSION))
         {
             REPORT_FAILED_METHOD("name of local variable: " << name->bytes <<
                 " in " << attr_name << " attribute is not stored as unqualified name");
@@ -1247,10 +1296,18 @@
                 "in " << attr_name << " attribute");
             return false;
         }
+        //See specification about index value 4.8.11 and 4.8.12
+        if((descriptor->bytes[0] == 'D' || descriptor->bytes[0] == 'J')
+                && index >= _max_locals - 1)
+        {
+            REPORT_FAILED_METHOD("invalid local index "
+                << index << " in " << attr_name << " attribute");
+            return false;
+        }
 
         if (index >= _max_locals) {
             REPORT_FAILED_METHOD("invalid local index "
-                "in " << attr_name << " attribute");
+                << index << " in " << attr_name << " attribute");
             return false;
         }
 
@@ -1274,8 +1331,8 @@
                 &&table->table[j].length == table->table[i].length
                 &&table->table[j].index == table->table[i].index)
             {
-                REPORT_FAILED_METHOD("Duplicate attribute "<< attr_name
-                    <<" for local variable ");
+                REPORT_FAILED_METHOD("Duplicate local variable "<< table->table[j].name
+                    << " in attribute " << attr_name);
                 return false;
             }
         }
@@ -1328,9 +1385,9 @@
         || (_byte_code_length >= (1<<16)))
     {
         REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError",
-            _class->get_name()->bytes << ": bytecode length for method "
-            << _name->bytes << _descriptor->bytes
-            << " has zero or exceeding length");
+            _class->get_name()->bytes << ": invalid bytecode length "
+            << _byte_code_length << " for method "
+            << _name->bytes << _descriptor->bytes);
         return false;
     }
 
@@ -1648,10 +1705,11 @@
 {
     if(!Class_Member::parse(clss, cfs))
         return false;
-
-    if(!(_name == env.Init_String || _name == env.Clinit_String))
+    //check name only if flag verify_all is set from command line
+    if(env.verify_all && !(_name == env.Init_String || _name == env.Clinit_String))
     {
-        if(!check_method_name(_name->bytes, _name->len))
+        if(!check_method_name(_name->bytes, _name->len,
+                clss->get_version() < JAVA5_CLASS_FILE_VERSION))
         {
             REPORT_FAILED_CLASS_FORMAT(clss, "illegal method name : " << _name->bytes);
             return false;
@@ -1673,8 +1731,8 @@
     if(_arguments_slot_num > 255) {
         REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError",
             _class->get_name()->bytes <<
-            ": method has more than 255 arguments "
-            << _name->bytes );
+            ": method " << _name->bytes << _descriptor->bytes
+            << " has more than 255 arguments " );
         return false;
     }
     // checked method descriptor
@@ -1692,61 +1750,68 @@
     // check method access flags
     if(!is_clinit())
     {
-        if(is_private() && is_protected() || is_private() && is_public() || is_protected() && is_public())
-        {
-            bool bout = false;
-            //See specification 4.7 Methods about access_flags
-            REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError",
-                _class->get_name()->bytes << ": invalid combination of access flags ("
-                << ((bout = is_public())?"ACC_PUBLIC":"")
-                << (bout?"|":"")
-                << ((bout |= is_protected())?"ACC_PROTECTED":"")
-                << (bout?"|":"")
-                << (is_private()?"ACC_PRIVATE":"")
-                << ") for method "
-                << _name->bytes << _descriptor->bytes);
-            return false;
-        }
-        if(is_abstract()
-        && (is_final() || is_native() || is_private() || is_static() || is_strict() || is_synchronized()))
-        {
-            bool bout = false;
-            REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError",
-                _class->get_name()->bytes << ": invalid combination of access flags (ACC_ABSTRACT|"
-                << ((bout = is_final())?"ACC_FINAL":"")
-                << (bout?"|":"")
-                << ((bout |= is_native())?"ACC_NATIVE":"")
-                << (bout?"|":"")
-                << ((bout |= is_private())?"ACC_PRIVATE":"")
-                << (bout?"|":"")
-                << ((bout |= is_static())?"ACC_STATIC":"")
-                << (bout?"|":"")
-                << ((bout |= is_strict())?"ACC_STRICT":"")
-                << (bout?"|":"")
-                << ((bout |= is_synchronized())?"ACC_SYNCHRONIZED":"")
-                << ") for method "
-                << _name->bytes << _descriptor->bytes);
-            return false;
-        }
         if(_class->is_interface())
         {
             if(!(is_abstract() && is_public())){
                 REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError",
                     _class->get_name()->bytes << "." << _name->bytes << _descriptor->bytes
-                    << ": interface method must have access flags "
+                    << ": interface method must have both access flags "
                     "ACC_ABSTRACT and ACC_PUBLIC set"
                     );
                 return false;
             }
-            if(_access_flags & ~(ACC_ABSTRACT | ACC_PUBLIC | ACC_VARARGS | ACC_BRIDGE | ACC_SYNTHETIC)){
+            if(_access_flags & ~(ACC_ABSTRACT | ACC_PUBLIC | ACC_VARARGS
+                            | ACC_BRIDGE | ACC_SYNTHETIC)){
                 REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError",
-                    _class->get_name()->bytes << "." << _name->bytes << _descriptor->bytes
-                    << ": interface method cannot have access flags other then "
-                    "ACC_ABSTRACT, ACC_PUBLIC, ACC_VARARG, ACC_BRIDGES or ACC_SYNTHETIC set");
+                    _class->get_name()->bytes << " Interface method " 
+                    << _name->bytes << _descriptor->bytes 
+                    << " has invalid combination of access flags "
+                    << "0x" << std::hex << _access_flags);
                 return false;
             }
-        }
-
+            //for class file version lower than 49 these three flags should be set to zero
+            //See specification 4.6 Methods, for 1.4 Java.            
+            if(_class->get_version() < JAVA5_CLASS_FILE_VERSION){
+                _access_flags &= ~(ACC_BRIDGE | ACC_VARARGS | ACC_SYNTHETIC); 
+            }
+        } else {
+            if(is_private() && is_protected()
+                || is_private() && is_public()
+                || is_protected() && is_public())
+            {
+                //See specification 4.7 Methods about access_flags
+                REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError",
+                    _class->get_name()->bytes << "Method "
+                    << _name->bytes << _descriptor->bytes 
+                    << " has invalid combination of access flags "
+                    << "0x" << std::hex << _access_flags);
+                return false;
+            }
+            if(is_abstract()
+            && (is_final() || is_native() || is_private()
+                    || is_static() || is_strict() || is_synchronized()))
+            {
+                bool bout = false;
+                REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError",
+                    _class->get_name()->bytes << " Method " 
+                    << _name->bytes << _descriptor->bytes
+                    << " has invalid combination of access flags "
+                    << "0x" << std::hex << _access_flags);
+                return false;
+            }
+            if(is_init()) {
+                if(_access_flags & ~(ACC_STRICT | ACC_VARARGS | ACC_SYNTHETIC
+                        | ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED))
+                {
+                    REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError",
+                        _class->get_name()->bytes << " Method " 
+                        << _name->bytes << _descriptor->bytes
+                        << " has invalid combination of access flags "
+                        << "0x" << std::hex << _access_flags);
+                    return false;
+                }    
+            }
+        }    
     } else {
         // Java VM specification
         // 4.7 Methods
@@ -1761,14 +1826,6 @@
         _access_flags |= ACC_STATIC;
     }
 
-    if(is_init() && (is_static() || is_final() || is_synchronized() || is_native() || is_abstract() || is_bridge())) {
-        REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError",
-            _class->get_name()->bytes << "." << _name->bytes << _descriptor->bytes
-            << ": constructor cannot have access flags other then "
-            "ACC_STRICT, ACC_VARARGS, ACC_SYNTHETIC and one of ACC_PUBLIC, ACC_PRIVATE, or ACC_PROTECTED set");
-        return false;
-    }
-
     //check method attributes
     uint16 attr_count;
     if(!cfs.parse_u2_be(&attr_count)) {
@@ -1823,16 +1880,43 @@
             break;
 
         case ATTR_RuntimeInvisibleParameterAnnotations:
-            if(++numRuntimeInvisibleParameterAnnotations > 1) {
-                REPORT_FAILED_CLASS_FORMAT(clss,
-                    "more than one RuntimeInvisibleParameterAnnotations attribute");
-                return false;
-            }
-
-            if (!cfs.skip(attr_len))
             {
-                REPORT_FAILED_METHOD("error skipping RuntimeInvisibleParameterAnnotations");
-                return false;
+                //RuntimeInvisibleParameterAnnotations attribute is parsed only if
+                //command line option -Xinvisible is set. See specification 4.8.17.
+                if(env.retain_invisible_annotations) {
+                    if(++numRuntimeInvisibleParameterAnnotations > 1) {
+                        REPORT_FAILED_CLASS_FORMAT(clss,
+                            "more than one RuntimeInvisibleParameterAnnotations attribute");
+                        return false;
+                    }
+                    if (!cfs.parse_u1(&_num_invisible_param_annotations)) {
+                        REPORT_FAILED_CLASS_FORMAT(clss,
+                            "cannot parse number of InvisibleParameterAnnotations");
+                        return false;
+                    }
+                    uint32 read_len = 1;
+                    if (_num_invisible_param_annotations) {
+                        uint32 len =
+                            parse_parameter_annotations(&_invisible_param_annotations,
+                                        _num_invisible_param_annotations, cfs, _class);  
+                        if(len == 0)
+                            return false;
+                        read_len += len;                        
+                    }
+                    if (attr_len != read_len) {
+                        REPORT_FAILED_METHOD(
+                            "error parsing InvisibleParameterAnnotations attribute"
+                            << "; declared length " << attr_len
+                            << " does not match actual " << read_len);
+                        return false;
+                    }
+                } else {
+                    if (!cfs.skip(attr_len))
+                    {
+                        REPORT_FAILED_METHOD("error skipping RuntimeInvisibleParameterAnnotations");
+                        return false;
+                    }
+                }
             }
             break;
 
@@ -1852,17 +1936,11 @@
                 }
                 uint32 read_len = 1;
                 if (_num_param_annotations) {
-                    _param_annotations = (AnnotationTable**)_class->get_class_loader()->Alloc(
-                        _num_param_annotations * sizeof (AnnotationTable*));
-                    //FIXME: verav should throw OOM
-                    for (unsigned i = 0; i < _num_param_annotations; i++)
-                    {
-                        uint32 next_len = parse_annotation_table(_param_annotations + i, cfs, _class);
-                        if (next_len == 0) {
-                            return false;
-                        }
-                        read_len += next_len;
-                    }
+                    uint32 len = parse_parameter_annotations(&_param_annotations,
+                                    _num_param_annotations, cfs, _class);
+                    if(len == 0)
+                        return false;
+                    read_len += len;
                 }
                 if (attr_len != read_len) {
                     REPORT_FAILED_METHOD(
@@ -1943,6 +2021,8 @@
                 }
 
                 uint32 read_len = parse_annotation_table(&_annotations, cfs, clss);
+                if(read_len == 0)
+                    return false;
                 if (attr_len != read_len) {
                     REPORT_FAILED_CLASS_FORMAT(clss,
                         "error parsing Annotations attribute"
@@ -1961,11 +2041,26 @@
                         "more than one RuntimeInvisibleAnnotations attribute");
                     return false;
                 }
-
-                if(!cfs.skip(attr_len)) {
-                    REPORT_FAILED_CLASS_FORMAT(clss,
-                        "failed to skip RuntimeInvisibleAnnotations attribute");
-                    return false;
+                //RuntimeInvisibleAnnotations attribute is parsed only if
+                //command line option -Xinvisible is set. See specification 4.8.15.
+                if(env.retain_invisible_annotations) {
+                    uint32 read_len =
+                        parse_annotation_table(&_invisible_annotations, cfs, clss);
+                    if(read_len == 0)
+                        return false;
+                    if (attr_len != read_len) {
+                        REPORT_FAILED_CLASS_FORMAT(clss,
+                            "error parsing RuntimeInvisibleAnnotations attribute"
+                            << "; declared length " << attr_len
+                            << " does not match actual " << read_len);
+                        return false;
+                    }
+                }else {
+                    if(!cfs.skip(attr_len)) {
+                        REPORT_FAILED_CLASS_FORMAT(clss,
+                            "failed to skip RuntimeInvisibleAnnotations attribute");
+                        return false;
+                    }
                 }
             }
             break;
@@ -2043,7 +2138,7 @@
     unsigned short last_nonstatic_field = (unsigned short)num_fields_in_class_file;
     for(i=0; i < num_fields_in_class_file; i++) {
         Field fd;
-        if(!fd.parse(this, cfs))
+        if(!fd.parse(*env, this, cfs))
             return false;
         if(fd.is_static()) {
             m_fields[m_num_static_fields] = fd;
@@ -2170,14 +2265,14 @@
                 id_len++;
             }else
             {
-                if(!check_field_name(name, id_len))
+                if(!check_field_name(name, id_len, false))
                     return false;
                 id_len = 0;
                 name = iterator;
                 name++;
             }
         }
-    return check_field_name(name, id_len);
+    return check_field_name(name, id_len, false);
     }
     return false; //unreacheable code
 }
@@ -2187,19 +2282,21 @@
 {
     // buffer ends before len
     if(!cfs.have(len))
-        return false;
+        return NULL;
 
     // get utf8 bytes and move buffer pointer
-    const char* utf8data = (const char*)cfs.get_and_skip(len);
+    uint8* utf8data = (uint8*)cfs.get_and_skip(len);
 
     // FIXME: decode 6-byte Java 1.5 encoding
 
     // check utf8 correctness
-    if(memchr(utf8data, 0, len) != NULL)
-        return false;
+    int i;
+    for(i = 0; i < len && utf8data[i] != 0x00 && utf8data[i] < 0xf0; i++);
+    if(i < len)
+        return NULL;
 
     // then lookup on utf8 bytes and return string
-    return string_pool.lookup(utf8data, len);
+    return string_pool.lookup((const char*)utf8data, len);
 }
 
 
@@ -2208,7 +2305,7 @@
 {
     uint16 len;
     if(!cfs.parse_u2_be(&len))
-        return false;
+        return NULL;
 
     return class_file_parse_utf8data(string_pool, cfs, len);
 }
@@ -2304,7 +2401,11 @@
                     return false;
                 }
                 // skip next constant pool entry as it is used by next 4 bytes of Long/Double
-                cp_tags[i+1] = cp_tags[i];
+                if(i + 1 < m_size) {
+                    cp_tags[i+1] = CONSTANT_UnusedEntry;
+                    m_entries[i+1].CONSTANT_8byte.high_bytes = m_entries[i].CONSTANT_8byte.high_bytes;
+                    m_entries[i+1].CONSTANT_8byte.low_bytes = m_entries[i].CONSTANT_8byte.low_bytes;
+                }    
                 i++;
                 break;
 
@@ -2337,7 +2438,7 @@
                 break;
             default:
                 REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError",
-                    clss->get_name()->bytes << ": unknown constant pool tag " << cp_tags[i]);
+                    clss->get_name()->bytes << ": unknown constant pool tag " << "0x" << std::hex << (int)cp_tags[i]);
                 return false;
         }
     }
@@ -2347,8 +2448,6 @@
 
 bool ConstantPool::check(Global_Env* env, Class* clss)
 {
-
-
     for(unsigned i = 1; i < m_size; i++) {
         switch(unsigned char tag = get_tag(i))
         {
@@ -2409,7 +2508,8 @@
                 //check method name
                 if(name != env->Init_String)
                 {
-                    if(!check_method_name(name->bytes,name->len))
+                    if(!check_method_name(name->bytes,name->len,
+                            clss->get_version() < JAVA5_CLASS_FILE_VERSION))
                     {
                         REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError",
                             clss->get_name()->bytes << ": illegal method name for CONSTANT_Methodref entry: " << name->bytes);
@@ -2440,7 +2540,8 @@
             if(tag == CONSTANT_Fieldref)
             {
                 //check field name
-                if(!check_field_name(name->bytes, name->len))
+                if(!check_field_name(name->bytes, name->len,
+                        clss->get_version() < JAVA5_CLASS_FILE_VERSION))
                 {
                     REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError",
                         clss->get_name()->bytes << ": illegal filed name for CONSTANT_Filedref entry: " << name->bytes);
@@ -2458,7 +2559,8 @@
             {
                 //check method name, name can't be <init> or <clinit>
                 //See specification 4.5.2 about name_and_type_index last sentence.
-                if(!check_method_name(name->bytes, name->len))
+                if(!check_method_name(name->bytes, name->len,
+                        clss->get_version() < JAVA5_CLASS_FILE_VERSION))
                 {
                     REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError",
                         clss->get_name()->bytes << ": illegal filed name for CONSTANT_InterfaceMethod entry: " << name->bytes);
@@ -2495,11 +2597,12 @@
         case CONSTANT_Double:
             //check Long and Double indexes, n+1 index should be valid too.
             //See specification 4.5.5
-            if( i + 1 > m_size){
+            if(i + 1 == m_size){
                 REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError",
                     clss->get_name()->bytes << ": illegal indexes for Long or Double " << i << " and " << i + 1);
                 return false;
             }
+            i++;
             break;
         case CONSTANT_NameAndType:
         {
@@ -2647,7 +2750,7 @@
         return false;
     }
 
-    if(m_version == 49 && minor_version > 0)
+    if(m_version == JAVA5_CLASS_FILE_VERSION && minor_version > 0)
     {
         REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/UnsupportedClassVersionError",
             "unsupported class file version " << m_version << "." << minor_version);
@@ -2693,7 +2796,7 @@
         REPORT_FAILED_CLASS_FORMAT(this, "interface cannot be final");
         return false;
     }
-    //not only ACC_FINAL flag is prohibited if is_interface, also ACC_SUPER, ACC_SYNTHETIC, ACC_ENUM.
+    //not only ACC_FINAL flag is prohibited if is_interface, also ACC_SYNTHETIC and ACC_ENUM.
     if(is_interface() && (is_synthetic() || is_enum()))
     {
         REPORT_FAILED_CLASS_FORMAT(this,
@@ -2716,7 +2819,12 @@
         REPORT_FAILED_CLASS_FORMAT(this, "not interface can't be annotation");
         return false;
     }
-
+    //for class file version lower than 49 these three flags should be set to zero
+    //See specification 4.5 Fields, for 1.4 Java.    
+    if(m_version < JAVA5_CLASS_FILE_VERSION) {
+        m_access_flags &= ~(ACC_SYNTHETIC | ACC_ENUM | ACC_ANNOTATION);    
+    }
+    
     /*
      * parse this_class & super_class & verify their constant pool entries
      */
@@ -3098,9 +3206,11 @@
                     return false;
                 }
                 uint32 read_len = parse_annotation_table(&m_annotations, cfs, this);
+                if(attr_len == 0)
+                    return false;
                 if (attr_len != read_len) {
                     REPORT_FAILED_CLASS_FORMAT(this,
-                        "error parsing Annotations attribute"
+                        "error parsing RuntimeVisibleAnnotations attribute"
                         << "; declared length " << attr_len
                         << " does not match actual " << read_len);
                     return false;
@@ -3110,16 +3220,29 @@
 
         case ATTR_RuntimeInvisibleAnnotations:
             {
-                //ClassFile may contain at most one RuntimeInvisibleAnnotations attribute.
-                if(++numRuntimeInvisibleAnnotations > 1) {
-                    REPORT_FAILED_CLASS_FORMAT(this,
-                        "more than one RuntimeInvisibleAnnotations attribute");
-                    return false;
-                }
-                if(!cfs.skip(attr_len)) {
-                    REPORT_FAILED_CLASS_FORMAT(this,
-                        "failed to skip RuntimeInvisibleAnnotations attribute");
-                    return false;
+                if(env->retain_invisible_annotations) {
+                    //ClassFile may contain at most one RuntimeInvisibleAnnotations attribute.
+                    if(++numRuntimeInvisibleAnnotations > 1) {
+                        REPORT_FAILED_CLASS_FORMAT(this,
+                            "more than one RuntimeInvisibleAnnotations attribute");
+                        return false;
+                    }
+                    uint32 read_len = parse_annotation_table(&m_invisible_annotations, cfs, this);
+                    if(read_len == 0)
+                        return false;
+                    if (attr_len != read_len) {
+                        REPORT_FAILED_CLASS_FORMAT(this,
+                            "error parsing RuntimeInvisibleAnnotations attribute"
+                            << "; declared length " << attr_len
+                            << " does not match actual " << read_len);
+                        return false;
+                    }
+                }else {
+                    if(!cfs.skip(attr_len)) {
+                        REPORT_FAILED_CLASS_FORMAT(this,
+                            "failed to skip RuntimeInvisibleAnnotations attribute");
+                        return false;
+                    }
                 }
             }
             break;

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp?view=diff&rev=490202&r1=490201&r2=490202
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp Mon Dec 25 16:07:25 2006
@@ -136,6 +136,7 @@
 
     verify_all = false;
     pin_interned_strings = false; 
+    retain_invisible_annotations = false;
 
     // initialize critical sections
     p_jit_a_method_lock = new Lock_Manager();

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Resolve.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Resolve.cpp?view=diff&rev=490202&r1=490201&r2=490202
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Resolve.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Resolve.cpp Mon Dec 25 16:07:25 2006
@@ -1048,6 +1048,7 @@
             return true;
         case CONSTANT_Double: // fall through
         case CONSTANT_Long:
+        case CONSTANT_UnusedEntry:
             return true;
     }
     return false;

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/parse_arguments.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/parse_arguments.cpp?view=diff&rev=490202&r1=490201&r2=490202
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/parse_arguments.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/parse_arguments.cpp Mon Dec 25 16:07:25 2006
@@ -177,6 +177,8 @@
         "              Log verbose output to a file\n"
         "    -Xverify\n"
         "              Do full bytecode verification\n"
+        "    -Xinvisible\n"
+        "              Retain invisible annotations at runtime\n"
         "    -Xfileline\n"
         "              Add source information to logging messages\n"
         "    -Xthread\n"
@@ -434,6 +436,9 @@
         }
         else if (strcmp(option, "-Xdebug") == 0) {
             // Do nothing, this option is only for compatibility with old JREs
+        }
+        else if (strcmp(option, "-Xinvisible") == 0) {
+            p_env->retain_invisible_annotations = true;
         }
         else if (strcmp(option, "-Xverify") == 0) {
             p_env->verify_all = true;

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMGenericsAndAnnotations.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMGenericsAndAnnotations.cpp?view=diff&rev=490202&r1=490201&r2=490202
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMGenericsAndAnnotations.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMGenericsAndAnnotations.cpp Mon Dec 25 16:07:25 2006
@@ -62,7 +62,9 @@
 {
     Class_Member* member = (Class_Member*) ((POINTER_SIZE_INT) jmember);
     TRACE("Requested annotations for member " << member);
-    return get_annotations(jenv, member->get_declared_annotations(), member->get_class());
+    return get_annotations(jenv, member->get_declared_annotations(),
+                member->get_declared_invisible_annotations(),
+                member->get_class());
 }
 
 JNIEXPORT jobjectArray JNICALL Java_org_apache_harmony_vm_VMGenericsAndAnnotations_getDeclaredAnnotations__Ljava_lang_Class_2
@@ -70,7 +72,8 @@
 {
     Class* clazz = jclass_to_struct_Class(jclazz);
     TRACE("Requested annotations for class " << clazz);
-    return get_annotations(jenv, clazz->get_annotations(), clazz);
+    return get_annotations(jenv, clazz->get_annotations(),
+                clazz->get_invisible_annotations(), clazz);
 }
 
 JNIEXPORT jobjectArray JNICALL Java_org_apache_harmony_vm_VMGenericsAndAnnotations_getParameterAnnotations
@@ -83,7 +86,8 @@
     static Class* array_class = genv->LoadCoreClass(
         "[Ljava/lang/annotation/Annotation;");
 
-    unsigned num = method->get_num_param_annotations();
+    unsigned param_num = method->get_num_param_annotations();
+    unsigned num = param_num + method->get_num_invisible_param_annotations();
     TRACE("Requested parameters annotations for method " << method
         << "; num=" << num);
 
@@ -113,8 +117,11 @@
         return NULL;
     }
 
-    for (unsigned i = 0; i < num; ++i) {
-        jobject element = get_annotations(jenv, method->get_param_annotations(i), declaring_class);
+    unsigned i;
+    for (i = 0; i < param_num; ++i) {
+        jobject element = get_annotations(jenv,
+                                method->get_param_annotations(i),
+                                NULL, declaring_class);
         if (!element) {
             assert(exn_raised());
             return NULL;
@@ -123,7 +130,19 @@
             assert(!exn_raised());
         }
     }
-
+    for (i = param_num; i < num; ++i) {
+        jobject element = get_annotations(jenv, NULL,
+                method->get_invisible_param_annotations(i - param_num),
+                declaring_class);
+        if (!element) {
+            assert(exn_raised());
+            return NULL;
+        } else {
+            SetObjectArrayElement(jenv, array, i, element);
+            assert(!exn_raised());
+        }
+    }
+    
     return array;
 }
 

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/reflection/annotations.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/reflection/annotations.cpp?view=diff&rev=490202&r1=490201&r2=490202
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/reflection/annotations.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/reflection/annotations.cpp Mon Dec 25 16:07:25 2006
@@ -36,10 +36,15 @@
 #include "primitives_support.h"
 #include "vm_log.h"
 
-jobjectArray get_annotations(JNIEnv* jenv, AnnotationTable* table, Class* clss) 
+jobjectArray get_annotations(JNIEnv* jenv, AnnotationTable* table, AnnotationTable* inv_table, Class* clss) 
 {
-    unsigned num = table ? table->length : 0;
-    TRACE("annotations table size = " << num);
+    unsigned table_num = table ? table->length : 0;
+    TRACE("annotations table size = " << table_num);
+    
+    unsigned inv_table_num = inv_table ? inv_table->length : 0;
+    TRACE("invisible annotations table size = " << inv_table_num);
+    
+    unsigned num = table_num + inv_table_num;
 
     static Class* antn_class = jni_get_vm_env(jenv)->LoadCoreClass(
         "java/lang/annotation/Annotation");
@@ -52,7 +57,8 @@
         return NULL;
     }
 
-    for (unsigned i = 0; i < num; ++i) {
+    unsigned i;
+    for (i = 0; i < table_num; ++i) {
         jobject element = resolve_annotation(jenv, table->table[i], clss);
         if (!element) {
             assert(exn_raised());
@@ -62,7 +68,16 @@
             assert(!exn_raised());
         }
     }
-
+    for (i = table_num; i < num; ++i) {
+        jobject element = resolve_annotation(jenv, inv_table->table[i - table_num], clss);
+        if (!element) {
+            assert(exn_raised());
+            return NULL;
+        } else {
+            SetObjectArrayElement(jenv, array, i, element);
+            assert(!exn_raised());
+        }
+    }
     return array;
 }
 



Mime
View raw message