pxb1988/dex2jar · error · RecognitionException
RecognitionException on invalid annotation element keyword…
Error message
RecognitionException on invalid annotation element keyword (expected 'c')
What it means
Same sAnnotationElement rule as error 130: this alternative expects the keyword 'c' (a class-descriptor annotation element, parsed as sClassDesc and converted via Type.getType). When the ID token matched by xid is not 'c', the guard if(!"c".contains($xid.text)){ throw new RecognitionException(input); } throws at Jasmin.g:1042, signaling the parser to backtrack. If no other alternative matches the element either, the whole .annotation block fails to assemble.
Solutions
- Write the class-type annotation element exactly as 'c = <classDesc>' e.g. 'c = Ljava/lang/Class;.class' in the .j file
- Verify letter case: the guard compares against lowercase 'c', so 'C' will not match
- If the element is really an enum/string/primitive, use the corresponding keyword ('e', 's', or the token B/Z/S/C/I/J) instead
- Regenerate the Jasmin file from the original dex/jar with a d2j-compatible dumper rather than editing by hand
Example fix
// before classvalue = Ljava/lang/Class;.TYPE // after c = Ljava/lang/Class;.TYPE
Defensive patterns
Strategy: validation
Validate before calling
// validate class-descriptor annotation elements use keyword 'c'
for (String line : jasminLines) {
if (line.matches("\\s*[A-Za-z_][\\w$]*\\s*=\\s*L[^ ]*\\.[^ ]+\\s*$") && !line.trim().startsWith("e ") && !line.matches("\\s*c\\s*=.*")) {
throw new IllegalArgumentException("class annotation element must start with 'c = ': " + line.trim());
}
} Try / catch
try {
Jasmin asm = new Jasmin(new FileReader(jasminFile));
asm.parse();
} catch (RecognitionException | RuntimeException e) {
LOG.error("annotation element in {} rejected (expect keyword 'c' before class desc)", jasminFile, e);
throw new JasminSyntaxException("Invalid class annotation element", e);
} Prevention
- Always prefix class-type annotation values with 'c = ' in .j files
- Do not use 'C' or full words like 'class' — the grammar compares against lowercase "c"
- Diff generated Jasmin against a known-good d2j dump when porting from Soot syntax
- Parse files in CI with the assembler to catch syntax drift early
When it happens
Trigger: An annotation element in a Jasmin file that supplies a class descriptor after 'name = ' but whose keyword ID is not exactly 'c', e.g. 'value = Ljava/lang/Class;.TYPE' written as 'classvalue = Ljava/lang/Class;.TYPE' or with the keyword omitted, inside '.annotation' ... '.end annotation' passed to the d2j-jasmin assembler.
Common situations: Migrating Jasmin output from Soot or older assemblers whose annotation-element syntax used full words ('class', 'enum', 'string') instead of the single letters this grammar hard-codes; typos like 'C' vs 'c' (grammar is case-sensitive); copy-pasted annotation lines edited by hand.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- RecognitionException on invalid annotation element keyword…
- RecognitionException on invalid annotation element keyword…
- Fail to assemble
- can't pase string
- not support access flags " + name
AI-assisted analysis of pxb1988/dex2jar@b5bda4fb49 (2026-09-08).
Data as JSON: /api/errors/e7c1ecc15990b1d8.
Report an issue: GitHub.
Appendix: source
Thrown at d2j-jasmin/src/main/antlr3/com/googlecode/d2j/jasmin/Jasmin.g:1042
| '.float_kind' a=STRING b=INT {$nn=unEscapeString($a.text); $v=parseFloat($b.text);}
| '.doub_kind' a=STRING b=(INT|LONG) {$nn=unEscapeString($a.text); $v=parseDouble($b.text);}
| '.str_kind' a=STRING b=STRING {$nn=unEscapeString($a.text); $v=unEscapeString($b.text);}
| '.enum_kind' a=STRING b=STRING {$nn=unEscapeString($a.text); String on[]=parseOwnerAndName($b.text);$v=new String[]{on[0],on[1]};}
| '.cls_kind' a=STRING b=STRING {$nn=unEscapeString($a.text); $v=Type.getType(unEscapeString($b.text));}
| '.arr_kind' a=STRING {List<Object> array=new ArrayList<>();} (t=sAnnotationElementSoot{array.add($t.v);})* '.end' '.arr_elem' {$nn=unEscapeString($a.text); $v=array;}
| '.ann_kind' a=STRING q=sSubannotationSoot '.end' '.annot_elem' {$nn=unEscapeString($a.text); $v=$q.v;})
;
sSubannotationSoot returns[AnnotationNode v]
: '.annotation' a=STRING { $v=new AnnotationNode(unEscapeString($a.text)); }
(t=sAnnotationElementSoot {$v.visit($t.nn,$t.v);} )*
'.end' '.annotation'
;
sAnnotationElement @init{List<Object> array = new ArrayList<Object>(); AnnotationNode _t= currentAnnotationVisitor;}
: a=sId (
xid=ID { if(!"e".contains($xid.text)){ throw new RecognitionException(input);} } c=OBJECT_TYPE '=' b=sWord { _t.visit($a.text,new String[]{$c.text,$b.text}); }
| AT b2=OBJECT_TYPE '=' { currentAnnotationVisitor=new AnnotationNode($b2.text);} sSubannotation { _t.visit($a.text,currentAnnotationVisitor); }
| xid=ID { if(!"c".contains($xid.text)){ throw new RecognitionException(input);} } '=' b1=sClassDesc { currentAnnotationVisitor.visit($a.text,Type.getType($b1.text)); }
| xid=ID { if(!"s".contains($xid.text)){ throw new RecognitionException(input);} } '=' b3=STRING { currentAnnotationVisitor.visit($a.text,unEscapeString($b3.text)); }
| UP_B '=' b4=INT { currentAnnotationVisitor.visit($a.text,(byte)parseInt($b4.text)); }
| UP_Z '=' b5=INT { currentAnnotationVisitor.visit($a.text,0!=parseInt($b5.text)); }
| UP_S '=' b6=INT { currentAnnotationVisitor.visit($a.text,(short)parseInt($b6.text)); }
| UP_C '=' b7=INT { currentAnnotationVisitor.visit($a.text,(char)parseInt($b7.text)); }
| UP_I '=' b8=INT { currentAnnotationVisitor.visit($a.text,parseInt($b8.text)); }
| UP_J '=' b9=(INT|LONG) { currentAnnotationVisitor.visit($a.text,parseLong($b9.text)); }
| UP_F '=' b10=(INT|FLOAT|DOUBLE) { currentAnnotationVisitor.visit($a.text,parseFloat($b10.text)); }
| UP_D '=' b11=(INT|FLOAT|DOUBLE) { currentAnnotationVisitor.visit($a.text,parseDouble($b11.text)); }
| ARRAY_B '=' (b12=INT {array.add((byte)parseInt($b12.text));} )+ { currentAnnotationVisitor.visit($a.text,array); }
| ARRAY_Z '=' (b13=INT {array.add(0!=parseInt($b13.text));} )+ { currentAnnotationVisitor.visit($a.text,array); }
| ARRAY_S '=' (b14=INT {array.add((short)parseInt($b14.text));} )+ { currentAnnotationVisitor.visit($a.text,array); }
| ARRAY_C '=' (b15=INT {array.add((char)parseInt($b15.text));} )+ { currentAnnotationVisitor.visit($a.text,array); }
| ARRAY_I '=' (b16=INT {array.add(parseInt($b16.text));} )+ { currentAnnotationVisitor.visit($a.text,array); }
| ARRAY_J '=' (b17=(INT|LONG) {array.add(parseLong($b17.text));} )+ { currentAnnotationVisitor.visit($a.text,array); }
| ARRAY_F '=' (b18=(INT|FLOAT|DOUBLE) {array.add(parseFloat($b18.text));} )+ { currentAnnotationVisitor.visit($a.text,array); }
| ARRAY_D '=' (b19=(INT|DOUBLE) {array.add(parseDouble($b19.text));} )+ { currentAnnotationVisitor.visit($a.text,array); }
| ARRAY_LOW_E c=OBJECT_TYPE '=' ((b1=sWord{ array.add(new String[]{$c.text,unEscape($b1.text)}); }|b2=STRING{ array.add(new String[]{$c.text,unEscapeString($b2.text)}); }|b3=DSTRING{ array.add(new String[]{$c.text,unEscapeString($b3.text)}); }) )+ { currentAnnotationVisitor.visit($a.text,array); }
View on GitHub (pinned to b5bda4fb49)