]> source.dussan.org Git - aspectj.git/commitdiff
very early java9 support - can resolve classes in jimages
authorAndy Clement <aclement@gopivotal.com>
Thu, 5 Mar 2015 00:05:27 +0000 (16:05 -0800)
committerAndy Clement <aclement@gopivotal.com>
Thu, 5 Mar 2015 00:05:27 +0000 (16:05 -0800)
13 files changed:
bcel-builder/testsrc/Play.java
build/usedForMavenUpload/aspectjrt.pom
build/usedForMavenUpload/aspectjtools.pom
build/usedForMavenUpload/aspectjweaver.pom
loadtime5/java5-src/org/aspectj/weaver/loadtime/Agent.java
loadtime5/loadtime5.mf.txt
org.eclipse.jdt.core/jdtcore-for-aspectj-src.zip
org.eclipse.jdt.core/jdtcore-for-aspectj.jar
org.eclipse.jdt.core/src/org/aspectj/org/eclipse/jdt/internal/compiler/ClassFile.java [new file with mode: 0644]
testing/newsrc/org/aspectj/testing/AjcTest.java
weaver/.classpath
weaver/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
weaver/src/org/aspectj/weaver/bcel/ClassPathManager.java

index 024ef7a6dfebe1b9175f5881e7392a04e1680888..9fef2fa6cc6d7b54fbf01b32d56110a35cf4f1e0 100644 (file)
@@ -7,6 +7,7 @@ import org.aspectj.apache.bcel.classfile.Field;
 import org.aspectj.apache.bcel.classfile.JavaClass;
 import org.aspectj.apache.bcel.classfile.Method;
 import org.aspectj.apache.bcel.classfile.Unknown;
+import org.aspectj.apache.bcel.classfile.annotation.RuntimeAnnos;
 
 
 public class Play {
@@ -65,13 +66,17 @@ public class Play {
 //             }
        }
 
-       private static void printUsefulAttributes(Attribute[] attributes) {
+       private static void printUsefulAttributes(Attribute[] attributes) throws Exception {
                for (Attribute attribute: attributes) {
                        String n = attribute.getName();
-                       if (n.equals("RuntimeInvisibleTypeAnnotations") ||
-                               n.equals("RuntimeVisibleTypeAnnotations")) {
-                               Unknown unknown = (Unknown)attribute;
-                               byte[] bs = unknown.getBytes();
+                       if (n.equals("RuntimeInvisibleAnnotations") ||
+                               n.equals("RuntimeVisibleAnnotations")) {
+                               RuntimeAnnos ra = (RuntimeAnnos)attribute;
+                               // private byte[] annotation_data;
+                               java.lang.reflect.Field f = RuntimeAnnos.class.getDeclaredField("annotation_data");
+                               f.setAccessible(true);
+                               byte[] bs = (byte[])f.get(ra);
+//                             byte[] bs = unknown.getBytes();
                                printBytes(bs);
                        }
                }
index 25c6146d75af0b4c29a99ebe88a6bab9091ec117..f468c4f5a1de5c60bc227fa8bfb69a70bc24c9bc 100644 (file)
@@ -5,7 +5,7 @@
   <groupId>org.aspectj</groupId>
   <artifactId>aspectjrt</artifactId>
   <packaging>jar</packaging>
-  <version>1.8.4.BUILD-SNAPSHOT</version>
+  <version>1.9.0.BETA-1</version>
   <name>AspectJ runtime</name>
   <description>The runtime needed to execute a program using AspectJ</description>
   <url>http://www.aspectj.org</url>
index defa88acf07ee28a54a844d32a6bdad8f5e4bfe1..0a7eca459675f1de59934f4441093292abfe02ce 100644 (file)
@@ -5,7 +5,7 @@
   <groupId>org.aspectj</groupId>
   <artifactId>aspectjtools</artifactId>
   <packaging>jar</packaging>
-  <version>1.8.4.BUILD-SNAPSHOT</version>
+  <version>1.9.0.BETA-1</version>
   <name>AspectJ tools</name>
   <description>Tools from the AspectJ project</description>
   <url>http://www.aspectj.org</url>
index ad82e409327ea22ae006df43c401c4691acf10f1..391bc4d44267158495641396f8c474ddfba2e55b 100644 (file)
@@ -5,7 +5,7 @@
   <groupId>org.aspectj</groupId>
   <artifactId>aspectjweaver</artifactId>
   <packaging>jar</packaging>
-  <version>1.8.4.BUILD-SNAPSHOT</version>
+  <version>1.9.0.BETA-1</version>
   <name>AspectJ weaver</name>
   <description>The AspectJ weaver introduces advices to java classes</description>
   <url>http://www.aspectj.org</url>
index 920d04e04b7a9ac48d498c227b204d937745ca5a..5bd6d67718f4b587d78f0975987546e30c27ee03 100644 (file)
@@ -47,12 +47,18 @@ public class Agent {
         s_instrumentation.addTransformer(s_transformer);
     }
 
+    public static void agentmain(String options, Instrumentation instrumentation) {
+        premain(options, instrumentation);
+    }
+
     /**
      * Returns the Instrumentation system level instance
      */
     public static Instrumentation getInstrumentation() {
         if (s_instrumentation == null) {
-            throw new UnsupportedOperationException("Java 5 was not started with preMain -javaagent for AspectJ");
+            throw new UnsupportedOperationException(
+                "AspectJ weaving agent was neither started via '-javaagent' (preMain) " +
+                "nor attached via 'VirtualMachine.loadAgent' (agentMain)");
         }
         return s_instrumentation;
     }
index 57529ee049f3816e034ba5ae76fe99bfb1255693..729cae693ec0c67802f3c4499a17c06fc5532242 100644 (file)
@@ -7,4 +7,5 @@ Implementation-Title: org.aspectj.weaver
 Implementation-Version: @build.version.short@
 Implementation-Vendor: @company.name@
 Premain-Class: org.aspectj.weaver.loadtime.Agent
+Agent-Class: org.aspectj.weaver.loadtime.Agent
 Can-Redefine-Classes: true
index c35fb62cd40f0f4b09e916142c974ee1b5cc24cb..f619bc2d028ad4436c43335a7091503529aa9d52 100644 (file)
Binary files a/org.eclipse.jdt.core/jdtcore-for-aspectj-src.zip and b/org.eclipse.jdt.core/jdtcore-for-aspectj-src.zip differ
index cd33770a9ec8a2d97d2b9c29e7e33e2a6a5fb8f6..7793000884b5349281f90c7d47229ff20c9f9168 100644 (file)
Binary files a/org.eclipse.jdt.core/jdtcore-for-aspectj.jar and b/org.eclipse.jdt.core/jdtcore-for-aspectj.jar differ
diff --git a/org.eclipse.jdt.core/src/org/aspectj/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/src/org/aspectj/org/eclipse/jdt/internal/compiler/ClassFile.java
new file mode 100644 (file)
index 0000000..e3d1c41
--- /dev/null
@@ -0,0 +1,6784 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jesper S Moller - Contributions for
+ *                                                     Bug 405066 - [1.8][compiler][codegen] Implement code generation infrastructure for JSR335             
+ *                                                     Bug 406982 - [1.8][compiler] Generation of MethodParameters Attribute in classfile
+ *                                                     Bug 416885 - [1.8][compiler]IncompatibleClassChange error (edit)
+ *                                                     Bug 412149 - [1.8][compiler] Emit repeated annotations into the designated container
+ *     Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
+ *                          Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
+ *                          Bug 409236 - [1.8][compiler] Type annotations on intersection cast types dropped by code generator
+ *                          Bug 409246 - [1.8][compiler] Type annotations on catch parameters not handled properly
+ *                          Bug 415541 - [1.8][compiler] Type annotations in the body of static initializer get dropped
+ *                          Bug 415399 - [1.8][compiler] Type annotations on constructor results dropped by the code generator
+ *                          Bug 415470 - [1.8][compiler] Type annotations on class declaration go vanishing
+ *                          Bug 405104 - [1.8][compiler][codegen] Implement support for serializeable lambdas
+ *                          Bug 434556 - Broken class file generated for incorrect annotation usage
+ *     Stephan Herrmann - Contribution for
+ *                                                     Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables
+ *******************************************************************************/
+package org.aspectj.org.eclipse.jdt.internal.compiler;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.aspectj.org.eclipse.jdt.core.compiler.CategorizedProblem;
+import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
+import org.aspectj.org.eclipse.jdt.core.compiler.IProblem;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FunctionalExpression;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Receiver;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeParameter;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.AnnotationContext;
+import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.AnnotationTargetTypeConstants;
+import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
+import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.CodeStream;
+import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
+import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.ExceptionLabel;
+import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.Opcodes;
+import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.StackMapFrame;
+import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream;
+import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.TypeAnnotationCodeStream;
+import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.ExceptionMarker;
+import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.StackDepthMarker;
+import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.StackMarker;
+import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.VerificationTypeInfo;
+import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.aspectj.org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.aspectj.org.eclipse.jdt.internal.compiler.impl.StringConstant;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Binding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
+import org.aspectj.org.eclipse.jdt.internal.compiler.problem.ShouldNotImplement;
+import org.aspectj.org.eclipse.jdt.internal.compiler.util.Messages;
+import org.aspectj.org.eclipse.jdt.internal.compiler.util.Util;
+
+/**
+ * Represents a class file wrapper on bytes, it is aware of its actual
+ * type name.
+ *
+ * Public APIs are listed below:
+ *
+ * byte[] getBytes();
+ *             Answer the actual bytes of the class file
+ *
+ * char[][] getCompoundName();
+ *             Answer the compound name of the class file.
+ *             For example, {{java}, {util}, {Hashtable}}.
+ *
+ * byte[] getReducedBytes();
+ *             Answer a smaller byte format, which is only contains some structural
+ *      information. Those bytes are decodable with a regular class file reader,
+ *      such as DietClassFileReader
+ */
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class ClassFile implements TypeConstants, TypeIds {
+
+       private byte[] bytes;
+       public CodeStream codeStream;
+       public ConstantPool constantPool;
+
+       public int constantPoolOffset;
+
+       // the header contains all the bytes till the end of the constant pool
+       public byte[] contents;
+
+       public int contentsOffset;
+
+       protected boolean creatingProblemType;
+
+       public ClassFile enclosingClassFile;
+       public byte[] header;
+       // that collection contains all the remaining bytes of the .class file
+       public int headerOffset;
+       public Set innerClassesBindings;
+       public List bootstrapMethods = null;
+       public int methodCount;
+       public int methodCountOffset;
+       // pool managment
+       boolean isShared = false;
+       // used to generate private access methods
+       // debug and stack map attributes
+       public int produceAttributes;
+       public SourceTypeBinding referenceBinding;
+       public boolean isNestedType;
+       public long targetJDK;
+
+       public List missingTypes = null;
+
+       public Set visitedTypes;
+
+       public static final int INITIAL_CONTENTS_SIZE = 400;
+       public static final int INITIAL_HEADER_SIZE = 1500;
+       public static final int INNER_CLASSES_SIZE = 5;
+
+       /**
+        * INTERNAL USE-ONLY
+        * Request the creation of a ClassFile compatible representation of a problematic type
+        *
+        * @param typeDeclaration org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration
+        * @param unitResult org.aspectj.org.eclipse.jdt.internal.compiler.CompilationUnitResult
+        */
+       public static void createProblemType(TypeDeclaration typeDeclaration, CompilationResult unitResult) {
+               SourceTypeBinding typeBinding = typeDeclaration.binding;
+               ClassFile classFile = ClassFile.getNewInstance(typeBinding);
+               classFile.initialize(typeBinding, null, true);
+
+               if (typeBinding.hasMemberTypes()) {
+                       // see bug 180109
+                       ReferenceBinding[] members = typeBinding.memberTypes;
+                       for (int i = 0, l = members.length; i < l; i++)
+                               classFile.recordInnerClasses(members[i]);
+               }
+               // TODO (olivier) handle cases where a field cannot be generated (name too long)
+               // TODO (olivier) handle too many methods
+               // inner attributes
+               if (typeBinding.isNestedType()) {
+                       classFile.recordInnerClasses(typeBinding);
+               }
+               TypeVariableBinding[] typeVariables = typeBinding.typeVariables();
+               for (int i = 0, max = typeVariables.length; i < max; i++) {
+                       TypeVariableBinding typeVariableBinding = typeVariables[i];
+                       if ((typeVariableBinding.tagBits & TagBits.ContainsNestedTypeReferences) != 0) {
+                               Util.recordNestedType(classFile, typeVariableBinding);
+                       }
+               }
+               // add its fields
+               FieldBinding[] fields = typeBinding.fields();
+               if ((fields != null) && (fields != Binding.NO_FIELDS)) {
+                       classFile.addFieldInfos();
+               } else {
+                       // we have to set the number of fields to be equals to 0
+                       classFile.contents[classFile.contentsOffset++] = 0;
+                       classFile.contents[classFile.contentsOffset++] = 0;
+               }
+               // leave some space for the methodCount
+               classFile.setForMethodInfos();
+               // add its user defined methods
+               int problemsLength;
+               CategorizedProblem[] problems = unitResult.getErrors();
+               if (problems == null) {
+                       problems = new CategorizedProblem[0];
+               }
+               CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
+               System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+
+               AbstractMethodDeclaration[] methodDecls = typeDeclaration.methods;
+               boolean abstractMethodsOnly = false;
+               if (methodDecls != null) {
+                       if (typeBinding.isInterface()) {
+                               if (typeBinding.scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_8)
+                                       abstractMethodsOnly = true;
+                               // We generate a clinit which contains all the problems, since we may not be able to generate problem methods (< 1.8) and problem constructors (all levels).
+                               classFile.addProblemClinit(problemsCopy);
+                       }
+                       for (int i = 0, length = methodDecls.length; i < length; i++) {
+                               AbstractMethodDeclaration methodDecl = methodDecls[i];
+                               MethodBinding method = methodDecl.binding;
+                               if (method == null) continue;
+                               if (abstractMethodsOnly) {
+                                       method.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract;
+                               }
+                               if (method.isConstructor()) {
+                                       if (typeBinding.isInterface()) continue;
+                                       classFile.addProblemConstructor(methodDecl, method, problemsCopy);
+                               } else if (method.isAbstract()) {
+                                       classFile.addAbstractMethod(methodDecl, method);
+                               } else {
+                                       classFile.addProblemMethod(methodDecl, method, problemsCopy);
+                               }
+                       }
+                       // add abstract methods
+                       classFile.addDefaultAbstractMethods();
+               }
+
+               // propagate generation of (problem) member types
+               if (typeDeclaration.memberTypes != null) {
+                       for (int i = 0, max = typeDeclaration.memberTypes.length; i < max; i++) {
+                               TypeDeclaration memberType = typeDeclaration.memberTypes[i];
+                               if (memberType.binding != null) {
+                                       ClassFile.createProblemType(memberType, unitResult);
+                               }
+                       }
+               }
+               classFile.addAttributes();
+               unitResult.record(typeBinding.constantPoolName(), classFile);
+       }
+       public static ClassFile getNewInstance(SourceTypeBinding typeBinding) {
+               LookupEnvironment env = typeBinding.scope.environment();
+               return env.classFilePool.acquire(typeBinding);
+       }
+       /**
+        * INTERNAL USE-ONLY
+        * This methods creates a new instance of the receiver.
+        */
+       protected ClassFile() {
+               // default constructor for subclasses
+       }
+
+       public ClassFile(SourceTypeBinding typeBinding) {
+               // default constructor for subclasses
+               this.constantPool = new ConstantPool(this);
+               final CompilerOptions options = typeBinding.scope.compilerOptions();
+               this.targetJDK = options.targetJDK;
+               this.produceAttributes = options.produceDebugAttributes;
+               this.referenceBinding = typeBinding;
+               this.isNestedType = typeBinding.isNestedType();
+               if (this.targetJDK >= ClassFileConstants.JDK1_6) {
+                       this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP_TABLE;
+                       if (this.targetJDK >= ClassFileConstants.JDK1_8) {
+                               this.produceAttributes |= ClassFileConstants.ATTR_TYPE_ANNOTATION;
+                               this.codeStream = new TypeAnnotationCodeStream(this);
+                               if (options.produceMethodParameters) {
+                                       this.produceAttributes |= ClassFileConstants.ATTR_METHOD_PARAMETERS;
+                               }
+                       } else {
+                               this.codeStream = new StackMapFrameCodeStream(this);
+                       }
+               } else if (this.targetJDK == ClassFileConstants.CLDC_1_1) {
+                       this.targetJDK = ClassFileConstants.JDK1_1; // put back 45.3
+                       this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP;
+                       this.codeStream = new StackMapFrameCodeStream(this);
+               } else {
+                       this.codeStream = new CodeStream(this);
+               }
+               initByteArrays();
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a bogus method.
+        *
+        * @param method org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+        * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+        */
+       public void addAbstractMethod(
+                       AbstractMethodDeclaration method,
+                       MethodBinding methodBinding) {
+
+               this.generateMethodInfoHeader(methodBinding);
+               int methodAttributeOffset = this.contentsOffset;
+               int attributeNumber = this.generateMethodInfoAttributes(methodBinding);
+               completeMethodInfo(methodBinding, methodAttributeOffset, attributeNumber);
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This methods generate all the attributes for the receiver.
+        * For a class they could be:
+        * - source file attribute
+        * - inner classes attribute
+        * - deprecated attribute
+        */
+       public void addAttributes() {
+               // update the method count
+               this.contents[this.methodCountOffset++] = (byte) (this.methodCount >> 8);
+               this.contents[this.methodCountOffset] = (byte) this.methodCount;
+
+               int attributesNumber = 0;
+               // leave two bytes for the number of attributes and store the current offset
+               int attributeOffset = this.contentsOffset;
+               this.contentsOffset += 2;
+
+               // source attribute
+               if ((this.produceAttributes & ClassFileConstants.ATTR_SOURCE) != 0) {
+                       String fullFileName =
+                               new String(this.referenceBinding.scope.referenceCompilationUnit().getFileName());
+                       fullFileName = fullFileName.replace('\\', '/');
+                       int lastIndex = fullFileName.lastIndexOf('/');
+                       if (lastIndex != -1) {
+                               fullFileName = fullFileName.substring(lastIndex + 1, fullFileName.length());
+                       }
+                       attributesNumber += generateSourceAttribute(fullFileName);
+               }
+               // Deprecated attribute
+               if (this.referenceBinding.isDeprecated()) {
+                       // check that there is enough space to write all the bytes for the field info corresponding
+                       // to the @fieldBinding
+                       attributesNumber += generateDeprecatedAttribute();
+               }
+               // add signature attribute
+               char[] genericSignature = this.referenceBinding.genericSignature();
+               if (genericSignature != null) {
+                       attributesNumber += generateSignatureAttribute(genericSignature);
+               }
+               if (this.targetJDK >= ClassFileConstants.JDK1_5
+                               && this.referenceBinding.isNestedType()
+                               && !this.referenceBinding.isMemberType()) {
+                       // add enclosing method attribute (1.5 mode only)
+                       attributesNumber += generateEnclosingMethodAttribute();
+               }
+               if (this.targetJDK >= ClassFileConstants.JDK1_4) {
+                       TypeDeclaration typeDeclaration = this.referenceBinding.scope.referenceContext;
+                       if (typeDeclaration != null) {
+                               // AspectJ Extension - use the original array if its set
+                               // original code:
+                               // final Annotation[] annotations = typeDeclaration.annotations;
+                               // new code:
+                               Annotation[] annotations = typeDeclaration.originalAnnotations;
+                               if (annotations == null) annotations = typeDeclaration.annotations;
+                               // End AspectJ Extension
+                               if (annotations != null) {
+                                       long targetMask;
+                                       if (typeDeclaration.isPackageInfo())
+                                               targetMask = TagBits.AnnotationForPackage;
+                                       else if (this.referenceBinding.isAnnotationType())
+                                               targetMask = TagBits.AnnotationForType | TagBits.AnnotationForAnnotationType;
+                                       else
+                                               targetMask = TagBits.AnnotationForType | TagBits.AnnotationForTypeUse;
+                                       attributesNumber += generateRuntimeAnnotations(annotations, targetMask); 
+                               }
+                       }
+               }
+
+               if (this.referenceBinding.isHierarchyInconsistent()) {
+                       ReferenceBinding superclass = this.referenceBinding.superclass;
+                       if (superclass != null) {
+                               this.missingTypes = superclass.collectMissingTypes(this.missingTypes);
+                       }
+                       ReferenceBinding[] superInterfaces = this.referenceBinding.superInterfaces();
+                       for (int i = 0, max = superInterfaces.length; i < max; i++) {
+                               this.missingTypes = superInterfaces[i].collectMissingTypes(this.missingTypes);
+                       }
+                       attributesNumber += generateHierarchyInconsistentAttribute();
+               }
+               // Functional expression and lambda bootstrap methods
+               if (this.bootstrapMethods != null && !this.bootstrapMethods.isEmpty()) {
+                       attributesNumber += generateBootstrapMethods(this.bootstrapMethods);
+               }
+               // Inner class attribute
+               int numberOfInnerClasses = this.innerClassesBindings == null ? 0 : this.innerClassesBindings.size();
+               if (numberOfInnerClasses != 0) {
+                       ReferenceBinding[] innerClasses = new ReferenceBinding[numberOfInnerClasses];
+                       this.innerClassesBindings.toArray(innerClasses);
+                       Arrays.sort(innerClasses, new Comparator() {
+                               public int compare(Object o1, Object o2) {
+                                       TypeBinding binding1 = (TypeBinding) o1;
+                                       TypeBinding binding2 = (TypeBinding) o2;
+                                       return CharOperation.compareTo(binding1.constantPoolName(), binding2.constantPoolName());
+                               }
+                       });
+                       attributesNumber += generateInnerClassAttribute(numberOfInnerClasses, innerClasses);
+               }
+               if (this.missingTypes != null) {
+                       generateMissingTypesAttribute();
+                       attributesNumber++;
+               }
+               
+               attributesNumber += generateTypeAnnotationAttributeForTypeDeclaration();
+               
+               // AspectJ Extension
+           // write any "extraAttributes"
+           if (extraAttributes != null) {
+               for (int i=0, len=extraAttributes.size(); i < len; i++) {
+                   IAttribute attribute = (IAttribute)extraAttributes.get(i);
+                   short nameIndex = (short)constantPool.literalIndex(attribute.getNameChars());
+                   writeToContents(attribute.getAllBytes(nameIndex,constantPool));
+                   attributesNumber++;
+               }
+           }
+           //  End AspectJ Extension
+               
+               // update the number of attributes
+               if (attributeOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+               this.contents[attributeOffset++] = (byte) (attributesNumber >> 8);
+               this.contents[attributeOffset] = (byte) attributesNumber;
+
+               // resynchronize all offsets of the classfile
+               this.header = this.constantPool.poolContent;
+               this.headerOffset = this.constantPool.currentOffset;
+               int constantPoolCount = this.constantPool.currentIndex;
+               this.header[this.constantPoolOffset++] = (byte) (constantPoolCount >> 8);
+               this.header[this.constantPoolOffset] = (byte) constantPoolCount;
+       }
+       /**
+        * INTERNAL USE-ONLY
+        * This methods generate all the default abstract method infos that correpond to
+        * the abstract methods inherited from superinterfaces.
+        */
+       public void addDefaultAbstractMethods() { // default abstract methods
+               MethodBinding[] defaultAbstractMethods =
+                       this.referenceBinding.getDefaultAbstractMethods();
+               for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
+                       MethodBinding methodBinding = defaultAbstractMethods[i];
+                       generateMethodInfoHeader(methodBinding);
+                       int methodAttributeOffset = this.contentsOffset;
+                       int attributeNumber = generateMethodInfoAttributes(methodBinding);
+                       completeMethodInfo(methodBinding, methodAttributeOffset, attributeNumber);
+               }
+       }
+
+       private int addFieldAttributes(FieldBinding fieldBinding, int fieldAttributeOffset) {
+               int attributesNumber = 0;
+               // 4.7.2 only static constant fields get a ConstantAttribute
+               // Generate the constantValueAttribute
+               Constant fieldConstant = fieldBinding.constant();
+               if (fieldConstant != Constant.NotAConstant){
+                       attributesNumber += generateConstantValueAttribute(fieldConstant, fieldBinding, fieldAttributeOffset);
+               }
+               if (this.targetJDK < ClassFileConstants.JDK1_5 && fieldBinding.isSynthetic()) {
+                       attributesNumber += generateSyntheticAttribute();
+               }
+               if (fieldBinding.isDeprecated()) {
+                       attributesNumber += generateDeprecatedAttribute();
+               }
+               // add signature attribute
+               char[] genericSignature = fieldBinding.genericSignature();
+               if (genericSignature != null) {
+                       attributesNumber += generateSignatureAttribute(genericSignature);
+               }
+               if (this.targetJDK >= ClassFileConstants.JDK1_4) {
+                       FieldDeclaration fieldDeclaration = fieldBinding.sourceField();
+                       if (fieldDeclaration != null) {
+                               Annotation[] annotations = fieldDeclaration.annotations;
+                               if (annotations != null) {
+                                       attributesNumber += generateRuntimeAnnotations(annotations, TagBits.AnnotationForField);
+                               }
+
+                               if ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) {
+                                       List allTypeAnnotationContexts = new ArrayList();
+                                       if (annotations != null && (fieldDeclaration.bits & ASTNode.HasTypeAnnotations) != 0) {
+                                               fieldDeclaration.getAllAnnotationContexts(AnnotationTargetTypeConstants.FIELD, allTypeAnnotationContexts);
+                                       }
+                                       int invisibleTypeAnnotationsCounter = 0;
+                                       int visibleTypeAnnotationsCounter = 0;
+                                       TypeReference fieldType = fieldDeclaration.type;
+                                       if (fieldType != null && ((fieldType.bits & ASTNode.HasTypeAnnotations) != 0)) {
+                                               fieldType.getAllAnnotationContexts(AnnotationTargetTypeConstants.FIELD, allTypeAnnotationContexts);
+                                       }
+                                       int size = allTypeAnnotationContexts.size();
+                                       if (size != 0) {
+                                               AnnotationContext[] allTypeAnnotationContextsArray = new AnnotationContext[size];
+                                               allTypeAnnotationContexts.toArray(allTypeAnnotationContextsArray);
+                                               for (int i = 0, max = allTypeAnnotationContextsArray.length; i < max; i++) {
+                                                       AnnotationContext annotationContext = allTypeAnnotationContextsArray[i];
+                                                       if ((annotationContext.visibility & AnnotationContext.INVISIBLE) != 0) {
+                                                               invisibleTypeAnnotationsCounter++;
+                                                               allTypeAnnotationContexts.add(annotationContext);
+                                                       } else {
+                                                               visibleTypeAnnotationsCounter++;
+                                                               allTypeAnnotationContexts.add(annotationContext);
+                                                       }
+                                               }
+                                               attributesNumber += generateRuntimeTypeAnnotations(
+                                                               allTypeAnnotationContextsArray,
+                                                               visibleTypeAnnotationsCounter,
+                                                               invisibleTypeAnnotationsCounter);
+                                       }
+                               }
+                       }
+               }
+               if ((fieldBinding.tagBits & TagBits.HasMissingType) != 0) {
+                       this.missingTypes = fieldBinding.type.collectMissingTypes(this.missingTypes);
+               }
+               return attributesNumber;
+       }
+
+    //  AspectJ Extension
+       public List/*<IAttribute>*/ extraAttributes = new ArrayList(1);
+       //  End AspectJ Extension
+
+       /**
+        * INTERNAL USE-ONLY
+        * This methods generates the bytes for the given field binding
+        * @param fieldBinding the given field binding
+        */
+       private void addFieldInfo(FieldBinding fieldBinding) {
+               // check that there is enough space to write all the bytes for the field info corresponding
+               // to the @fieldBinding
+               if (this.contentsOffset + 8 >= this.contents.length) {
+                       resizeContents(8);
+               }
+               // Now we can generate all entries into the byte array
+               // First the accessFlags
+               int accessFlags = fieldBinding.getAccessFlags();
+               if (this.targetJDK < ClassFileConstants.JDK1_5) {
+                       // pre 1.5, synthetic was an attribute, not a modifier
+                       accessFlags &= ~ClassFileConstants.AccSynthetic;
+               }
+               this.contents[this.contentsOffset++] = (byte) (accessFlags >> 8);
+               this.contents[this.contentsOffset++] = (byte) accessFlags;
+               // Then the nameIndex
+               int nameIndex = this.constantPool.literalIndex(fieldBinding.name);
+               this.contents[this.contentsOffset++] = (byte) (nameIndex >> 8);
+               this.contents[this.contentsOffset++] = (byte) nameIndex;
+               // Then the descriptorIndex
+               int descriptorIndex = this.constantPool.literalIndex(fieldBinding.type);
+               this.contents[this.contentsOffset++] = (byte) (descriptorIndex >> 8);
+               this.contents[this.contentsOffset++] = (byte) descriptorIndex;
+               int fieldAttributeOffset = this.contentsOffset;
+               int attributeNumber = 0;
+               // leave some space for the number of attributes
+               this.contentsOffset += 2;
+               attributeNumber += addFieldAttributes(fieldBinding, fieldAttributeOffset);
+               if (this.contentsOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+               this.contents[fieldAttributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[fieldAttributeOffset] = (byte) attributeNumber;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This methods generate all the fields infos for the receiver.
+        * This includes:
+        * - a field info for each defined field of that class
+        * - a field info for each synthetic field (e.g. this$0)
+        */
+       /**
+        * INTERNAL USE-ONLY
+        * This methods generate all the fields infos for the receiver.
+        * This includes:
+        * - a field info for each defined field of that class
+        * - a field info for each synthetic field (e.g. this$0)
+        */
+       public void addFieldInfos() {
+               SourceTypeBinding currentBinding = this.referenceBinding;
+               FieldBinding[] syntheticFields = currentBinding.syntheticFields();
+               int fieldCount =        currentBinding.fieldCount() + (syntheticFields == null ? 0 : syntheticFields.length);
+
+               // write the number of fields
+               if (fieldCount > 0xFFFF) {
+                       this.referenceBinding.scope.problemReporter().tooManyFields(this.referenceBinding.scope.referenceType());
+               }
+               this.contents[this.contentsOffset++] = (byte) (fieldCount >> 8);
+               this.contents[this.contentsOffset++] = (byte) fieldCount;
+
+               FieldDeclaration[] fieldDecls = currentBinding.scope.referenceContext.fields;
+               for (int i = 0, max = fieldDecls == null ? 0 : fieldDecls.length; i < max; i++) {
+                       FieldDeclaration fieldDecl = fieldDecls[i];
+                       if (fieldDecl.binding != null) {
+                               addFieldInfo(fieldDecl.binding);
+                       }
+               }
+
+               if (syntheticFields != null) {
+                       for (int i = 0, max = syntheticFields.length; i < max; i++) {
+                               addFieldInfo(syntheticFields[i]);
+                       }
+               }
+       }
+
+       private void addMissingAbstractProblemMethod(MethodDeclaration methodDeclaration, MethodBinding methodBinding, CategorizedProblem problem, CompilationResult compilationResult) {
+               // always clear the strictfp/native/abstract bit for a problem method
+               generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(ClassFileConstants.AccStrictfp | ClassFileConstants.AccNative | ClassFileConstants.AccAbstract));
+               int methodAttributeOffset = this.contentsOffset;
+               int attributeNumber = generateMethodInfoAttributes(methodBinding);
+
+               // Code attribute
+               attributeNumber++;
+
+               int codeAttributeOffset = this.contentsOffset;
+               generateCodeAttributeHeader();
+               StringBuffer buffer = new StringBuffer(25);
+               buffer.append("\t"  + problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
+               buffer.insert(0, Messages.compilation_unresolvedProblem);
+               String problemString = buffer.toString();
+
+               this.codeStream.init(this);
+               this.codeStream.preserveUnusedLocals = true;
+               this.codeStream.initializeMaxLocals(methodBinding);
+
+               // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+               this.codeStream.generateCodeAttributeForProblemMethod(problemString);
+
+               completeCodeAttributeForMissingAbstractProblemMethod(
+                       methodBinding,
+                       codeAttributeOffset,
+                       compilationResult.getLineSeparatorPositions(),
+                       problem.getSourceLineNumber());
+
+               completeMethodInfo(methodBinding, methodAttributeOffset, attributeNumber);
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem clinit method info that correspond to a boggus method.
+        *
+        * @param problems org.aspectj.org.eclipse.jdt.internal.compiler.problem.Problem[]
+        */
+       public void addProblemClinit(CategorizedProblem[] problems) {
+               generateMethodInfoHeaderForClinit();
+               // leave two spaces for the number of attributes
+               this.contentsOffset -= 2;
+               int attributeOffset = this.contentsOffset;
+               this.contentsOffset += 2;
+               int attributeNumber = 0;
+
+               int codeAttributeOffset = this.contentsOffset;
+               generateCodeAttributeHeader();
+               this.codeStream.resetForProblemClinit(this);
+               String problemString = "" ; //$NON-NLS-1$
+               int problemLine = 0;
+               if (problems != null) {
+                       int max = problems.length;
+                       StringBuffer buffer = new StringBuffer(25);
+                       int count = 0;
+                       for (int i = 0; i < max; i++) {
+                               CategorizedProblem problem = problems[i];
+                               if ((problem != null) && (problem.isError())) {
+                                       buffer.append("\t"  +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
+                                       count++;
+                                       if (problemLine == 0) {
+                                               problemLine = problem.getSourceLineNumber();
+                                       }
+                                       problems[i] = null;
+                               }
+                       } // insert the top line afterwards, once knowing how many problems we have to consider
+                       if (count > 1) {
+                               buffer.insert(0, Messages.compilation_unresolvedProblems);
+                       } else {
+                               buffer.insert(0, Messages.compilation_unresolvedProblem);
+                       }
+                       problemString = buffer.toString();
+               }
+
+               // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+               this.codeStream.generateCodeAttributeForProblemMethod(problemString);
+               attributeNumber++; // code attribute
+               completeCodeAttributeForClinit(
+                       codeAttributeOffset,
+                       problemLine);
+               if (this.contentsOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+               this.contents[attributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[attributeOffset] = (byte) attributeNumber;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a boggus constructor.
+        *
+        * @param method org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+        * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+        * @param problems org.aspectj.org.eclipse.jdt.internal.compiler.problem.Problem[]
+        */
+       public void addProblemConstructor(
+               AbstractMethodDeclaration method,
+               MethodBinding methodBinding,
+               CategorizedProblem[] problems) {
+               
+               if (methodBinding.declaringClass.isInterface()) {
+                       method.abort(ProblemSeverities.AbortType, null);
+               }
+
+               // always clear the strictfp/native/abstract bit for a problem method
+               generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(ClassFileConstants.AccStrictfp | ClassFileConstants.AccNative | ClassFileConstants.AccAbstract));
+               int methodAttributeOffset = this.contentsOffset;
+               int attributesNumber = generateMethodInfoAttributes(methodBinding);
+
+               // Code attribute
+               attributesNumber++;
+               int codeAttributeOffset = this.contentsOffset;
+               generateCodeAttributeHeader();
+               this.codeStream.reset(method, this);
+               String problemString = "" ; //$NON-NLS-1$
+               int problemLine = 0;
+               if (problems != null) {
+                       int max = problems.length;
+                       StringBuffer buffer = new StringBuffer(25);
+                       int count = 0;
+                       for (int i = 0; i < max; i++) {
+                               CategorizedProblem problem = problems[i];
+                               if ((problem != null) && (problem.isError())) {
+                                       buffer.append("\t"  +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
+                                       count++;
+                                       if (problemLine == 0) {
+                                               problemLine = problem.getSourceLineNumber();
+                                       }
+                               }
+                       } // insert the top line afterwards, once knowing how many problems we have to consider
+                       if (count > 1) {
+                               buffer.insert(0, Messages.compilation_unresolvedProblems);
+                       } else {
+                               buffer.insert(0, Messages.compilation_unresolvedProblem);
+                       }
+                       problemString = buffer.toString();
+               }
+
+               // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+               this.codeStream.generateCodeAttributeForProblemMethod(problemString);
+               completeCodeAttributeForProblemMethod(
+                       method,
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .getLineSeparatorPositions(),
+                       problemLine);
+               completeMethodInfo(methodBinding, methodAttributeOffset, attributesNumber);
+       }
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a boggus constructor.
+        * Reset the position inside the contents byte array to the savedOffset.
+        *
+        * @param method org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+        * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+        * @param problems org.aspectj.org.eclipse.jdt.internal.compiler.problem.Problem[]
+        * @param savedOffset <CODE>int</CODE>
+        */
+       public void addProblemConstructor(
+               AbstractMethodDeclaration method,
+               MethodBinding methodBinding,
+               CategorizedProblem[] problems,
+               int savedOffset) {
+               // we need to move back the contentsOffset to the value at the beginning of the method
+               this.contentsOffset = savedOffset;
+               this.methodCount--; // we need to remove the method that causes the problem
+               addProblemConstructor(method, methodBinding, problems);
+       }
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a boggus method.
+        *
+        * @param method org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+        * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+        * @param problems org.aspectj.org.eclipse.jdt.internal.compiler.problem.Problem[]
+        */
+       public void addProblemMethod(
+               AbstractMethodDeclaration method,
+               MethodBinding methodBinding,
+               CategorizedProblem[] problems) {
+               if (methodBinding.isAbstract() && methodBinding.declaringClass.isInterface()) {
+                       method.abort(ProblemSeverities.AbortType, null);
+               }
+               // always clear the strictfp/native/abstract bit for a problem method
+               generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(ClassFileConstants.AccStrictfp | ClassFileConstants.AccNative | ClassFileConstants.AccAbstract));
+               int methodAttributeOffset = this.contentsOffset;
+               int attributesNumber = generateMethodInfoAttributes(methodBinding);
+
+               // Code attribute
+               attributesNumber++;
+
+               int codeAttributeOffset = this.contentsOffset;
+               generateCodeAttributeHeader();
+               this.codeStream.reset(method, this);
+               String problemString = "" ; //$NON-NLS-1$
+               int problemLine = 0;
+               if (problems != null) {
+                       int max = problems.length;
+                       StringBuffer buffer = new StringBuffer(25);
+                       int count = 0;
+                       for (int i = 0; i < max; i++) {
+                               CategorizedProblem problem = problems[i];
+                               if ((problem != null)
+                                       && (problem.isError())
+                                       && (problem.getSourceStart() >= method.declarationSourceStart)
+                                       && (problem.getSourceEnd() <= method.declarationSourceEnd)) {
+                                       buffer.append("\t"  +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
+                                       count++;
+                                       if (problemLine == 0) {
+                                               problemLine = problem.getSourceLineNumber();
+                                       }
+                                       problems[i] = null;
+                               }
+                       } // insert the top line afterwards, once knowing how many problems we have to consider
+                       if (count > 1) {
+                               buffer.insert(0, Messages.compilation_unresolvedProblems);
+                       } else {
+                               buffer.insert(0, Messages.compilation_unresolvedProblem);
+                       }
+                       problemString = buffer.toString();
+               }
+
+               // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+               this.codeStream.generateCodeAttributeForProblemMethod(problemString);
+               completeCodeAttributeForProblemMethod(
+                       method,
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .getLineSeparatorPositions(),
+                       problemLine);
+               completeMethodInfo(methodBinding, methodAttributeOffset, attributesNumber);
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a boggus method.
+        * Reset the position inside the contents byte array to the savedOffset.
+        *
+        * @param method org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+        * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+        * @param problems org.aspectj.org.eclipse.jdt.internal.compiler.problem.Problem[]
+        * @param savedOffset <CODE>int</CODE>
+        */
+       public void addProblemMethod(
+               AbstractMethodDeclaration method,
+               MethodBinding methodBinding,
+               CategorizedProblem[] problems,
+               int savedOffset) {
+               // we need to move back the contentsOffset to the value at the beginning of the method
+               this.contentsOffset = savedOffset;
+               this.methodCount--; // we need to remove the method that causes the problem
+               addProblemMethod(method, methodBinding, problems);
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for all the special method infos.
+        * They are:
+        * - synthetic access methods
+        * - default abstract methods
+        * - lambda methods.
+        */
+       public void addSpecialMethods() {
+
+               // add all methods (default abstract methods and synthetic)
+
+               // default abstract methods
+               generateMissingAbstractMethods(this.referenceBinding.scope.referenceType().missingAbstractMethods, this.referenceBinding.scope.referenceCompilationUnit().compilationResult);
+
+               MethodBinding[] defaultAbstractMethods = this.referenceBinding.getDefaultAbstractMethods();
+               for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
+                       MethodBinding methodBinding = defaultAbstractMethods[i];
+                       generateMethodInfoHeader(methodBinding);
+                       int methodAttributeOffset = this.contentsOffset;
+                       int attributeNumber = generateMethodInfoAttributes(methodBinding);
+                       completeMethodInfo(methodBinding, methodAttributeOffset, attributeNumber);
+               }
+               
+               // add synthetic methods infos
+               int emittedSyntheticsCount = 0;
+               boolean continueScanningSynthetics = true;
+               while (continueScanningSynthetics) {
+                       continueScanningSynthetics = false;
+                       SyntheticMethodBinding[] syntheticMethods = this.referenceBinding.syntheticMethods();
+                       int currentSyntheticsCount = syntheticMethods == null ? 0: syntheticMethods.length;
+                       if (emittedSyntheticsCount != currentSyntheticsCount) {
+                               for (int i = emittedSyntheticsCount, max = currentSyntheticsCount; i < max; i++) {
+                                       SyntheticMethodBinding syntheticMethod = syntheticMethods[i];
+                                       switch (syntheticMethod.purpose) {
+                                               case SyntheticMethodBinding.FieldReadAccess :
+                                               case SyntheticMethodBinding.SuperFieldReadAccess :
+                                                       // generate a method info to emulate an reading access to
+                                                       // a non-accessible field
+                                                       addSyntheticFieldReadAccessMethod(syntheticMethod);
+                                                       break;
+                                               case SyntheticMethodBinding.FieldWriteAccess :
+                                               case SyntheticMethodBinding.SuperFieldWriteAccess :
+                                                       // generate a method info to emulate an writing access to
+                                                       // a non-accessible field
+                                                       addSyntheticFieldWriteAccessMethod(syntheticMethod);
+                                                       break;
+                                               case SyntheticMethodBinding.MethodAccess :
+                                               case SyntheticMethodBinding.SuperMethodAccess :
+                                               case SyntheticMethodBinding.BridgeMethod :
+                                                       // generate a method info to emulate an access to a non-accessible method / super-method or bridge method
+                                                       addSyntheticMethodAccessMethod(syntheticMethod);
+                                                       break;
+                                               case SyntheticMethodBinding.ConstructorAccess :
+                                                       // generate a method info to emulate an access to a non-accessible constructor
+                                                       addSyntheticConstructorAccessMethod(syntheticMethod);
+                                                       break;
+                                               case SyntheticMethodBinding.EnumValues :
+                                                       // generate a method info to define <enum>#values()
+                                                       addSyntheticEnumValuesMethod(syntheticMethod);
+                                                       break;
+                                               case SyntheticMethodBinding.EnumValueOf :
+                                                       // generate a method info to define <enum>#valueOf(String)
+                                                       addSyntheticEnumValueOfMethod(syntheticMethod);
+                                                       break;
+                                               case SyntheticMethodBinding.SwitchTable :
+                                                       // generate a method info to define the switch table synthetic method
+                                                       addSyntheticSwitchTable(syntheticMethod);
+                                                       break;
+                                               case SyntheticMethodBinding.TooManyEnumsConstants :
+                                                       addSyntheticEnumInitializationMethod(syntheticMethod);
+                                                       break;
+                                               case SyntheticMethodBinding.LambdaMethod:
+                                                       syntheticMethod.lambda.generateCode(this.referenceBinding.scope, this);
+                                                       continueScanningSynthetics = true; // lambda code generation could schedule additional nested lambdas for code generation.
+                                                       break;
+                                               case SyntheticMethodBinding.ArrayConstructor:
+                                                       addSyntheticArrayConstructor(syntheticMethod);
+                                                       break;
+                                               case SyntheticMethodBinding.ArrayClone:
+                                                       addSyntheticArrayClone(syntheticMethod);
+                                                       break;
+                                               case SyntheticMethodBinding.FactoryMethod:
+                                                       addSyntheticFactoryMethod(syntheticMethod);
+                                                       break;  
+                                               case SyntheticMethodBinding.DeserializeLambda:
+                                                       // TODO [andy] do we need to do this after the loop to ensure it is done last?
+                                                       addSyntheticDeserializeLambda(syntheticMethod,this.referenceBinding.syntheticMethods()); 
+                                                       break;
+                                       }
+                               }
+                               emittedSyntheticsCount = currentSyntheticsCount;
+                       }
+               }
+       }
+
+       public void addSyntheticArrayConstructor(SyntheticMethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding);
+               int methodAttributeOffset = this.contentsOffset;
+               // this will add exception attribute, synthetic attribute, deprecated attribute,...
+               int attributeNumber = generateMethodInfoAttributes(methodBinding);
+               // Code attribute
+               int codeAttributeOffset = this.contentsOffset;
+               attributeNumber++; // add code attribute
+               generateCodeAttributeHeader();
+               this.codeStream.init(this);
+               this.codeStream.generateSyntheticBodyForArrayConstructor(methodBinding);
+               completeCodeAttributeForSyntheticMethod(
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .getLineSeparatorPositions());
+               // update the number of attributes
+               this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[methodAttributeOffset] = (byte) attributeNumber;
+       }
+       public void addSyntheticArrayClone(SyntheticMethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding);
+               int methodAttributeOffset = this.contentsOffset;
+               // this will add exception attribute, synthetic attribute, deprecated attribute,...
+               int attributeNumber = generateMethodInfoAttributes(methodBinding);
+               // Code attribute
+               int codeAttributeOffset = this.contentsOffset;
+               attributeNumber++; // add code attribute
+               generateCodeAttributeHeader();
+               this.codeStream.init(this);
+               this.codeStream.generateSyntheticBodyForArrayClone(methodBinding);
+               completeCodeAttributeForSyntheticMethod(
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .getLineSeparatorPositions());
+               // update the number of attributes
+               this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[methodAttributeOffset] = (byte) attributeNumber;
+       }
+       public void addSyntheticFactoryMethod(SyntheticMethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding);
+               int methodAttributeOffset = this.contentsOffset;
+               // this will add exception attribute, synthetic attribute, deprecated attribute,...
+               int attributeNumber = generateMethodInfoAttributes(methodBinding);
+               // Code attribute
+               int codeAttributeOffset = this.contentsOffset;
+               attributeNumber++; // add code attribute
+               generateCodeAttributeHeader();
+               this.codeStream.init(this);
+               this.codeStream.generateSyntheticBodyForFactoryMethod(methodBinding);
+               completeCodeAttributeForSyntheticMethod(
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .getLineSeparatorPositions());
+               // update the number of attributes
+               this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[methodAttributeOffset] = (byte) attributeNumber;
+       }
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the bytes for a synthetic method that provides an access to a private constructor.
+        *
+        * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+        */
+       public void addSyntheticConstructorAccessMethod(SyntheticMethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding);
+               int methodAttributeOffset = this.contentsOffset;
+               // this will add exception attribute, synthetic attribute, deprecated attribute,...
+               int attributeNumber = generateMethodInfoAttributes(methodBinding);
+               // Code attribute
+               int codeAttributeOffset = this.contentsOffset;
+               attributeNumber++; // add code attribute
+               generateCodeAttributeHeader();
+               this.codeStream.init(this);
+               this.codeStream.generateSyntheticBodyForConstructorAccess(methodBinding);
+               completeCodeAttributeForSyntheticMethod(
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .getLineSeparatorPositions());
+               // update the number of attributes
+               this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[methodAttributeOffset] = (byte) attributeNumber;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        *  Generate the bytes for a synthetic method that implements Enum#valueOf(String) for a given enum type
+        *
+        * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+        */
+       public void addSyntheticEnumValueOfMethod(SyntheticMethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding);
+               int methodAttributeOffset = this.contentsOffset;
+               // this will add exception attribute, synthetic attribute, deprecated attribute,...
+               int attributeNumber = generateMethodInfoAttributes(methodBinding);
+               // Code attribute
+               int codeAttributeOffset = this.contentsOffset;
+               attributeNumber++; // add code attribute
+               generateCodeAttributeHeader();
+               this.codeStream.init(this);
+               this.codeStream.generateSyntheticBodyForEnumValueOf(methodBinding);
+               completeCodeAttributeForSyntheticMethod(
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .getLineSeparatorPositions());
+               // update the number of attributes
+               if ((this.produceAttributes & ClassFileConstants.ATTR_METHOD_PARAMETERS) != 0) {
+                       attributeNumber += generateMethodParameters(methodBinding);
+               }
+               this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[methodAttributeOffset] = (byte) attributeNumber;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        *  Generate the bytes for a synthetic method that implements Enum#values() for a given enum type
+        *
+        * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+        */
+       public void addSyntheticEnumValuesMethod(SyntheticMethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding);
+               int methodAttributeOffset = this.contentsOffset;
+               // this will add exception attribute, synthetic attribute, deprecated attribute,...
+               int attributeNumber = generateMethodInfoAttributes(methodBinding);
+               // Code attribute
+               int codeAttributeOffset = this.contentsOffset;
+               attributeNumber++; // add code attribute
+               generateCodeAttributeHeader();
+               this.codeStream.init(this);
+               this.codeStream.generateSyntheticBodyForEnumValues(methodBinding);
+               completeCodeAttributeForSyntheticMethod(
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .getLineSeparatorPositions());
+               // update the number of attributes
+               this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[methodAttributeOffset] = (byte) attributeNumber;
+       }
+
+       public void addSyntheticEnumInitializationMethod(SyntheticMethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding);
+               int methodAttributeOffset = this.contentsOffset;
+               // this will add exception attribute, synthetic attribute, deprecated attribute,...
+               int attributeNumber = generateMethodInfoAttributes(methodBinding);
+               // Code attribute
+               int codeAttributeOffset = this.contentsOffset;
+               attributeNumber++; // add code attribute
+               generateCodeAttributeHeader();
+               this.codeStream.init(this);
+               this.codeStream.generateSyntheticBodyForEnumInitializationMethod(methodBinding);
+               completeCodeAttributeForSyntheticMethod(
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .getLineSeparatorPositions());
+               // update the number of attributes
+               this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[methodAttributeOffset] = (byte) attributeNumber;
+       }
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a synthetic method that
+        * generate an read access to a private field.
+        *
+        * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+        */
+       public void addSyntheticFieldReadAccessMethod(SyntheticMethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding);
+               int methodAttributeOffset = this.contentsOffset;
+               // this will add exception attribute, synthetic attribute, deprecated attribute,...
+               int attributeNumber = generateMethodInfoAttributes(methodBinding);
+               // Code attribute
+               int codeAttributeOffset = this.contentsOffset;
+               attributeNumber++; // add code attribute
+               generateCodeAttributeHeader();
+               this.codeStream.init(this);
+               this.codeStream.generateSyntheticBodyForFieldReadAccess(methodBinding);
+               completeCodeAttributeForSyntheticMethod(
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .getLineSeparatorPositions());
+               // update the number of attributes
+               this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[methodAttributeOffset] = (byte) attributeNumber;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a synthetic method that
+        * generate an write access to a private field.
+        *
+        * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+        */
+       public void addSyntheticFieldWriteAccessMethod(SyntheticMethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding);
+               int methodAttributeOffset = this.contentsOffset;
+               // this will add exception attribute, synthetic attribute, deprecated attribute,...
+               int attributeNumber = generateMethodInfoAttributes(methodBinding);
+               // Code attribute
+               int codeAttributeOffset = this.contentsOffset;
+               attributeNumber++; // add code attribute
+               generateCodeAttributeHeader();
+               this.codeStream.init(this);
+               this.codeStream.generateSyntheticBodyForFieldWriteAccess(methodBinding);
+               completeCodeAttributeForSyntheticMethod(
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .getLineSeparatorPositions());
+               // update the number of attributes
+               this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[methodAttributeOffset] = (byte) attributeNumber;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the bytes for a synthetic method that provides access to a private method.
+        *
+        * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+        */
+       public void addSyntheticMethodAccessMethod(SyntheticMethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding);
+               int methodAttributeOffset = this.contentsOffset;
+               // this will add exception attribute, synthetic attribute, deprecated attribute,...
+               int attributeNumber = generateMethodInfoAttributes(methodBinding);
+               // Code attribute
+               int codeAttributeOffset = this.contentsOffset;
+               attributeNumber++; // add code attribute
+               generateCodeAttributeHeader();
+               this.codeStream.init(this);
+               this.codeStream.generateSyntheticBodyForMethodAccess(methodBinding);
+               completeCodeAttributeForSyntheticMethod(
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .getLineSeparatorPositions());
+               // update the number of attributes
+               this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[methodAttributeOffset] = (byte) attributeNumber;
+       }
+
+       public void addSyntheticSwitchTable(SyntheticMethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding);
+               int methodAttributeOffset = this.contentsOffset;
+               // this will add exception attribute, synthetic attribute, deprecated attribute,...
+               int attributeNumber = generateMethodInfoAttributes(methodBinding);
+               // Code attribute
+               int codeAttributeOffset = this.contentsOffset;
+               attributeNumber++; // add code attribute
+               generateCodeAttributeHeader();
+               this.codeStream.init(this);
+               this.codeStream.generateSyntheticBodyForSwitchTable(methodBinding);
+               completeCodeAttributeForSyntheticMethod(
+                       true,
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .getLineSeparatorPositions());
+               // update the number of attributes
+               this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[methodAttributeOffset] = (byte) attributeNumber;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method completes the creation of the code attribute by setting
+        * - the attribute_length
+        * - max_stack
+        * - max_locals
+        * - code_length
+        * - exception table
+        * - and debug attributes if necessary.
+        *
+        * @param codeAttributeOffset <CODE>int</CODE>
+        */
+       public void completeCodeAttribute(int codeAttributeOffset) {
+               // reinitialize the localContents with the byte modified by the code stream
+               this.contents = this.codeStream.bCodeStream;
+               int localContentsOffset = this.codeStream.classFileOffset;
+               // codeAttributeOffset is the position inside localContents byte array before we started to write
+               // any information about the codeAttribute
+               // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
+               // to get the right position, 6 for the max_stack etc...
+               int code_length = this.codeStream.position;
+               if (code_length > 65535) {
+                       if (this.codeStream.methodDeclaration != null) {
+                               this.codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(this.codeStream.methodDeclaration);
+                       } else {
+                               this.codeStream.lambdaExpression.scope.problemReporter().bytecodeExceeds64KLimit(this.codeStream.lambdaExpression);
+                       }
+               }
+               if (localContentsOffset + 20 >= this.contents.length) {
+                       resizeContents(20);
+               }
+               int max_stack = this.codeStream.stackMax;
+               this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+               this.contents[codeAttributeOffset + 7] = (byte) max_stack;
+               int max_locals = this.codeStream.maxLocals;
+               this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+               this.contents[codeAttributeOffset + 9] = (byte) max_locals;
+               this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+               this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+               this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+               this.contents[codeAttributeOffset + 13] = (byte) code_length;
+
+               boolean addStackMaps = (this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0;
+               // write the exception table
+               ExceptionLabel[] exceptionLabels = this.codeStream.exceptionLabels;
+               int exceptionHandlersCount = 0; // each label holds one handler per range (start/end contiguous)
+               for (int i = 0, length = this.codeStream.exceptionLabelsCounter; i < length; i++) {
+                       exceptionHandlersCount += this.codeStream.exceptionLabels[i].getCount() / 2;
+               }
+               int exSize = exceptionHandlersCount * 8 + 2;
+               if (exSize + localContentsOffset >= this.contents.length) {
+                       resizeContents(exSize);
+               }
+               // there is no exception table, so we need to offset by 2 the current offset and move
+               // on the attribute generation
+               this.contents[localContentsOffset++] = (byte) (exceptionHandlersCount >> 8);
+               this.contents[localContentsOffset++] = (byte) exceptionHandlersCount;
+               for (int i = 0, max = this.codeStream.exceptionLabelsCounter; i < max; i++) {
+                       ExceptionLabel exceptionLabel = exceptionLabels[i];
+                       if (exceptionLabel != null) {
+                               int iRange = 0, maxRange = exceptionLabel.getCount();
+                               if ((maxRange & 1) != 0) {
+                                       if (this.codeStream.methodDeclaration != null) {
+                                               this.codeStream.methodDeclaration.scope.problemReporter().abortDueToInternalError(
+                                                               Messages.bind(Messages.abort_invalidExceptionAttribute, new String(this.codeStream.methodDeclaration.selector)),
+                                                               this.codeStream.methodDeclaration);
+                                       } else {
+                                               this.codeStream.lambdaExpression.scope.problemReporter().abortDueToInternalError(
+                                                               Messages.bind(Messages.abort_invalidExceptionAttribute, new String(this.codeStream.lambdaExpression.binding.selector)),
+                                                               this.codeStream.lambdaExpression);
+                                       }
+                               }
+                               while (iRange < maxRange) {
+                                       int start = exceptionLabel.ranges[iRange++]; // even ranges are start positions
+                                       this.contents[localContentsOffset++] = (byte) (start >> 8);
+                                       this.contents[localContentsOffset++] = (byte) start;
+                                       int end = exceptionLabel.ranges[iRange++]; // odd ranges are end positions
+                                       this.contents[localContentsOffset++] = (byte) (end >> 8);
+                                       this.contents[localContentsOffset++] = (byte) end;
+                                       int handlerPC = exceptionLabel.position;
+                                       if (addStackMaps) {
+                                               StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream;
+                                               stackMapFrameCodeStream.addFramePosition(handlerPC);
+//                                             stackMapFrameCodeStream.addExceptionMarker(handlerPC, exceptionLabel.exceptionType);
+                                       }
+                                       this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
+                                       this.contents[localContentsOffset++] = (byte) handlerPC;
+                                       if (exceptionLabel.exceptionType == null) {
+                                               // any exception handler
+                                               this.contents[localContentsOffset++] = 0;
+                                               this.contents[localContentsOffset++] = 0;
+                                       } else {
+                                               int nameIndex;
+                                               if (exceptionLabel.exceptionType == TypeBinding.NULL) {
+                                                       /* represents ClassNotFoundException, see class literal access*/
+                                                       nameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
+                                               } else {
+                                                       nameIndex = this.constantPool.literalIndexForType(exceptionLabel.exceptionType);
+                                               }
+                                               this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                                               this.contents[localContentsOffset++] = (byte) nameIndex;
+                                       }
+                               }
+                       }
+               }
+               // debug attributes
+               int codeAttributeAttributeOffset = localContentsOffset;
+               int attributesNumber = 0;
+               // leave two bytes for the attribute_length
+               localContentsOffset += 2;
+               if (localContentsOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+
+               this.contentsOffset = localContentsOffset;
+
+               // first we handle the linenumber attribute
+               if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
+                       attributesNumber += generateLineNumberAttribute();
+               }
+               // then we do the local variable attribute
+               if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
+                       final boolean methodDeclarationIsStatic = this.codeStream.methodDeclaration != null ? this.codeStream.methodDeclaration.isStatic() : this.codeStream.lambdaExpression.binding.isStatic();
+                       attributesNumber += generateLocalVariableTableAttribute(code_length, methodDeclarationIsStatic, false);
+               }
+
+               if (addStackMaps) {
+                       attributesNumber += generateStackMapTableAttribute(
+                                       this.codeStream.methodDeclaration != null ? this.codeStream.methodDeclaration.binding : this.codeStream.lambdaExpression.binding,
+                                       code_length,
+                                       codeAttributeOffset,
+                                       max_locals,
+                                       false);
+               }
+
+               if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
+                       attributesNumber += generateStackMapAttribute(
+                                       this.codeStream.methodDeclaration != null ? this.codeStream.methodDeclaration.binding : this.codeStream.lambdaExpression.binding,
+                                       code_length,
+                                       codeAttributeOffset,
+                                       max_locals,
+                                       false);
+               }
+               
+               if ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) {
+                       attributesNumber += generateTypeAnnotationsOnCodeAttribute();
+               }
+
+               this.contents[codeAttributeAttributeOffset++] = (byte) (attributesNumber >> 8);
+               this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber;
+
+               // update the attribute length
+               int codeAttributeLength = this.contentsOffset - (codeAttributeOffset + 6);
+               this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+               this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+               this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+               this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+       }
+       
+       public int generateTypeAnnotationsOnCodeAttribute() {
+               int attributesNumber = 0;
+               
+               List allTypeAnnotationContexts = ((TypeAnnotationCodeStream) this.codeStream).allTypeAnnotationContexts;
+               int invisibleTypeAnnotationsCounter = 0;
+               int visibleTypeAnnotationsCounter = 0;
+
+               for (int i = 0, max = this.codeStream.allLocalsCounter; i < max; i++) {
+                       LocalVariableBinding localVariable = this.codeStream.locals[i];
+                       if (localVariable.isCatchParameter()) continue;
+                       LocalDeclaration declaration = localVariable.declaration;
+                       if (declaration == null
+                                       || (declaration.isArgument() && ((declaration.bits & ASTNode.IsUnionType) == 0))
+                                       || (localVariable.initializationCount == 0)
+                                       || ((declaration.bits & ASTNode.HasTypeAnnotations) == 0)) {
+                               continue;
+                       }
+                       int targetType = ((localVariable.tagBits & TagBits.IsResource) == 0) ? AnnotationTargetTypeConstants.LOCAL_VARIABLE : AnnotationTargetTypeConstants.RESOURCE_VARIABLE;
+                       declaration.getAllAnnotationContexts(targetType, localVariable, allTypeAnnotationContexts);
+               }
+               
+               ExceptionLabel[] exceptionLabels = this.codeStream.exceptionLabels;
+               for (int i = 0, max = this.codeStream.exceptionLabelsCounter; i < max; i++) {
+                       ExceptionLabel exceptionLabel = exceptionLabels[i];
+                       if (exceptionLabel.exceptionTypeReference != null && (exceptionLabel.exceptionTypeReference.bits & ASTNode.HasTypeAnnotations) != 0) {
+                               exceptionLabel.exceptionTypeReference.getAllAnnotationContexts(AnnotationTargetTypeConstants.EXCEPTION_PARAMETER, i, allTypeAnnotationContexts, exceptionLabel.se7Annotations);
+                       }
+               }
+               
+               int size = allTypeAnnotationContexts.size();
+               if (size != 0) {
+                       AnnotationContext[] allTypeAnnotationContextsArray = new AnnotationContext[size];
+                       allTypeAnnotationContexts.toArray(allTypeAnnotationContextsArray);
+                       for (int j = 0, max2 = allTypeAnnotationContextsArray.length; j < max2; j++) {
+                               AnnotationContext annotationContext = allTypeAnnotationContextsArray[j];
+                               if ((annotationContext.visibility & AnnotationContext.INVISIBLE) != 0) {
+                                       invisibleTypeAnnotationsCounter++;
+                               } else {
+                                       visibleTypeAnnotationsCounter++;
+                               }
+                       }
+                       attributesNumber += generateRuntimeTypeAnnotations(
+                                       allTypeAnnotationContextsArray,
+                                       visibleTypeAnnotationsCounter,
+                                       invisibleTypeAnnotationsCounter);
+               }
+               return attributesNumber;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method completes the creation of the code attribute by setting
+        * - the attribute_length
+        * - max_stack
+        * - max_locals
+        * - code_length
+        * - exception table
+        * - and debug attributes if necessary.
+        *
+        * @param codeAttributeOffset <CODE>int</CODE>
+        */
+       public void completeCodeAttributeForClinit(int codeAttributeOffset) {
+               // reinitialize the contents with the byte modified by the code stream
+               this.contents = this.codeStream.bCodeStream;
+               int localContentsOffset = this.codeStream.classFileOffset;
+               // codeAttributeOffset is the position inside contents byte array before we started to write
+               // any information about the codeAttribute
+               // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
+               // to get the right position, 6 for the max_stack etc...
+               int code_length = this.codeStream.position;
+               if (code_length > 65535) {
+                       this.codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
+                               this.codeStream.methodDeclaration.scope.referenceType());
+               }
+               if (localContentsOffset + 20 >= this.contents.length) {
+                       resizeContents(20);
+               }
+               int max_stack = this.codeStream.stackMax;
+               this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+               this.contents[codeAttributeOffset + 7] = (byte) max_stack;
+               int max_locals = this.codeStream.maxLocals;
+               this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+               this.contents[codeAttributeOffset + 9] = (byte) max_locals;
+               this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+               this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+               this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+               this.contents[codeAttributeOffset + 13] = (byte) code_length;
+
+               boolean addStackMaps = (this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0;
+               // write the exception table
+               ExceptionLabel[] exceptionLabels = this.codeStream.exceptionLabels;
+               int exceptionHandlersCount = 0; // each label holds one handler per range (start/end contiguous)
+               for (int i = 0, length = this.codeStream.exceptionLabelsCounter; i < length; i++) {
+                       exceptionHandlersCount += this.codeStream.exceptionLabels[i].getCount() / 2;
+               }
+               int exSize = exceptionHandlersCount * 8 + 2;
+               if (exSize + localContentsOffset >= this.contents.length) {
+                       resizeContents(exSize);
+               }
+               // there is no exception table, so we need to offset by 2 the current offset and move
+               // on the attribute generation
+               this.contents[localContentsOffset++] = (byte) (exceptionHandlersCount >> 8);
+               this.contents[localContentsOffset++] = (byte) exceptionHandlersCount;
+               for (int i = 0, max = this.codeStream.exceptionLabelsCounter; i < max; i++) {
+                       ExceptionLabel exceptionLabel = exceptionLabels[i];
+                       if (exceptionLabel != null) {
+                               int iRange = 0, maxRange = exceptionLabel.getCount();
+                               if ((maxRange & 1) != 0) {
+                                       this.codeStream.methodDeclaration.scope.problemReporter().abortDueToInternalError(
+                                                       Messages.bind(Messages.abort_invalidExceptionAttribute, new String(this.codeStream.methodDeclaration.selector)),
+                                                       this.codeStream.methodDeclaration);
+                               }
+                               while  (iRange < maxRange) {
+                                       int start = exceptionLabel.ranges[iRange++]; // even ranges are start positions
+                                       this.contents[localContentsOffset++] = (byte) (start >> 8);
+                                       this.contents[localContentsOffset++] = (byte) start;
+                                       int end = exceptionLabel.ranges[iRange++]; // odd ranges are end positions
+                                       this.contents[localContentsOffset++] = (byte) (end >> 8);
+                                       this.contents[localContentsOffset++] = (byte) end;
+                                       int handlerPC = exceptionLabel.position;
+                                       this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
+                                       this.contents[localContentsOffset++] = (byte) handlerPC;
+                                       if (addStackMaps) {
+                                               StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream;
+                                               stackMapFrameCodeStream.addFramePosition(handlerPC);
+//                                             stackMapFrameCodeStream.addExceptionMarker(handlerPC, exceptionLabel.exceptionType);
+                                       }
+                                       if (exceptionLabel.exceptionType == null) {
+                                               // any exception handler
+                                               this.contents[localContentsOffset++] = 0;
+                                               this.contents[localContentsOffset++] = 0;
+                                       } else {
+                                               int nameIndex;
+                                               if (exceptionLabel.exceptionType == TypeBinding.NULL) {
+                                                       /* represents denote ClassNotFoundException, see class literal access*/
+                                                       nameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
+                                               } else {
+                                                       nameIndex = this.constantPool.literalIndexForType(exceptionLabel.exceptionType);
+                                               }
+                                               this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                                               this.contents[localContentsOffset++] = (byte) nameIndex;
+                                       }
+                               }
+                       }
+               }
+               // debug attributes
+               int codeAttributeAttributeOffset = localContentsOffset;
+               int attributesNumber = 0;
+               // leave two bytes for the attribute_length
+               localContentsOffset += 2;
+               if (localContentsOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+
+               this.contentsOffset = localContentsOffset;
+
+               // first we handle the linenumber attribute
+               if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
+                       attributesNumber += generateLineNumberAttribute();
+               }
+               // then we do the local variable attribute
+               if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
+                       attributesNumber += generateLocalVariableTableAttribute(code_length, true, false);
+               }
+
+               if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0) {
+                       attributesNumber += generateStackMapTableAttribute(
+                                       null,
+                                       code_length,
+                                       codeAttributeOffset,
+                                       max_locals,
+                                       true);
+               }
+
+               if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
+                       attributesNumber += generateStackMapAttribute(
+                                       null,
+                                       code_length,
+                                       codeAttributeOffset,
+                                       max_locals,
+                                       true);
+               }
+
+               if ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) {
+                       attributesNumber += generateTypeAnnotationsOnCodeAttribute();
+               }
+
+               // update the number of attributes
+               // ensure first that there is enough space available inside the contents array
+               if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+               this.contents[codeAttributeAttributeOffset++] = (byte) (attributesNumber >> 8);
+               this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber;
+               // update the attribute length
+               int codeAttributeLength = this.contentsOffset - (codeAttributeOffset + 6);
+               this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+               this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+               this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+               this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method completes the creation of the code attribute by setting
+        * - the attribute_length
+        * - max_stack
+        * - max_locals
+        * - code_length
+        * - exception table
+        * - and debug attributes if necessary.
+        */
+       public void completeCodeAttributeForClinit(
+                       int codeAttributeOffset,
+                       int problemLine) {
+               // reinitialize the contents with the byte modified by the code stream
+               this.contents = this.codeStream.bCodeStream;
+               int localContentsOffset = this.codeStream.classFileOffset;
+               // codeAttributeOffset is the position inside contents byte array before we started to write
+               // any information about the codeAttribute
+               // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
+               // to get the right position, 6 for the max_stack etc...
+               int code_length = this.codeStream.position;
+               if (code_length > 65535) {
+                       this.codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
+                               this.codeStream.methodDeclaration.scope.referenceType());
+               }
+               if (localContentsOffset + 20 >= this.contents.length) {
+                       resizeContents(20);
+               }
+               int max_stack = this.codeStream.stackMax;
+               this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+               this.contents[codeAttributeOffset + 7] = (byte) max_stack;
+               int max_locals = this.codeStream.maxLocals;
+               this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+               this.contents[codeAttributeOffset + 9] = (byte) max_locals;
+               this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+               this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+               this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+               this.contents[codeAttributeOffset + 13] = (byte) code_length;
+
+               // write the exception table
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+
+               // debug attributes
+               int codeAttributeAttributeOffset = localContentsOffset;
+               int attributesNumber = 0; // leave two bytes for the attribute_length
+               localContentsOffset += 2; // first we handle the linenumber attribute
+               if (localContentsOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+
+               this.contentsOffset = localContentsOffset;
+               // first we handle the linenumber attribute
+               if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
+                       attributesNumber += generateLineNumberAttribute(problemLine);
+               }
+               localContentsOffset = this.contentsOffset;
+               // then we do the local variable attribute
+               if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
+                       int localVariableNameIndex =
+                               this.constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+                       if (localContentsOffset + 8 >= this.contents.length) {
+                               resizeContents(8);
+                       }
+                       this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+                       this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 2;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       attributesNumber++;
+               }
+
+               this.contentsOffset = localContentsOffset;
+
+               if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0) {
+                       attributesNumber += generateStackMapTableAttribute(
+                                       null,
+                                       code_length,
+                                       codeAttributeOffset,
+                                       max_locals,
+                                       true);
+               }
+
+               if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
+                       attributesNumber += generateStackMapAttribute(
+                                       null,
+                                       code_length,
+                                       codeAttributeOffset,
+                                       max_locals,
+                                       true);
+               }
+
+               if ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) {
+                       attributesNumber += generateTypeAnnotationsOnCodeAttribute();
+               }
+               
+               // update the number of attributes
+               // ensure first that there is enough space available inside the contents array
+               if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+               this.contents[codeAttributeAttributeOffset++] = (byte) (attributesNumber >> 8);
+               this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber;
+               // update the attribute length
+               int codeAttributeLength = this.contentsOffset - (codeAttributeOffset + 6);
+               this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+               this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+               this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+               this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+       }
+
+
+       /**
+        *
+        */
+       public void completeCodeAttributeForMissingAbstractProblemMethod(
+                       MethodBinding binding,
+                       int codeAttributeOffset,
+                       int[] startLineIndexes,
+                       int problemLine) {
+               // reinitialize the localContents with the byte modified by the code stream
+               this.contents = this.codeStream.bCodeStream;
+               int localContentsOffset = this.codeStream.classFileOffset;
+               // codeAttributeOffset is the position inside localContents byte array before we started to write// any information about the codeAttribute// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset// to get the right position, 6 for the max_stack etc...
+               int max_stack = this.codeStream.stackMax;
+               this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+               this.contents[codeAttributeOffset + 7] = (byte) max_stack;
+               int max_locals = this.codeStream.maxLocals;
+               this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+               this.contents[codeAttributeOffset + 9] = (byte) max_locals;
+               int code_length = this.codeStream.position;
+               this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+               this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+               this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+               this.contents[codeAttributeOffset + 13] = (byte) code_length;
+               // write the exception table
+               if (localContentsOffset + 50 >= this.contents.length) {
+                       resizeContents(50);
+               }
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               // debug attributes
+               int codeAttributeAttributeOffset = localContentsOffset;
+               int attributesNumber = 0; // leave two bytes for the attribute_length
+               localContentsOffset += 2; // first we handle the linenumber attribute
+               if (localContentsOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+
+               this.contentsOffset = localContentsOffset;
+               if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
+                       if (problemLine == 0) {
+                               problemLine = Util.getLineNumber(binding.sourceStart(), startLineIndexes, 0, startLineIndexes.length-1);
+                       }
+                       attributesNumber += generateLineNumberAttribute(problemLine);
+               }
+
+               if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0) {
+                       attributesNumber += generateStackMapTableAttribute(
+                                       binding,
+                                       code_length,
+                                       codeAttributeOffset,
+                                       max_locals,
+                                       false);
+               }
+
+               if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
+                       attributesNumber += generateStackMapAttribute(
+                                       binding,
+                                       code_length,
+                                       codeAttributeOffset,
+                                       max_locals,
+                                       false);
+               }
+
+               // then we do the local variable attribute
+               // update the number of attributes// ensure first that there is enough space available inside the localContents array
+               if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+               this.contents[codeAttributeAttributeOffset++] = (byte) (attributesNumber >> 8);
+               this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber;
+               // update the attribute length
+               int codeAttributeLength = this.contentsOffset - (codeAttributeOffset + 6);
+               this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+               this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+               this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+               this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method completes the creation of the code attribute by setting
+        * - the attribute_length
+        * - max_stack
+        * - max_locals
+        * - code_length
+        * - exception table
+        * - and debug attributes if necessary.
+        *
+        * @param codeAttributeOffset <CODE>int</CODE>
+        */
+       public void completeCodeAttributeForProblemMethod(
+                       AbstractMethodDeclaration method,
+                       MethodBinding binding,
+                       int codeAttributeOffset,
+                       int[] startLineIndexes,
+                       int problemLine) {
+               // reinitialize the localContents with the byte modified by the code stream
+               this.contents = this.codeStream.bCodeStream;
+               int localContentsOffset = this.codeStream.classFileOffset;
+               // codeAttributeOffset is the position inside localContents byte array before we started to write// any information about the codeAttribute// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset// to get the right position, 6 for the max_stack etc...
+               int max_stack = this.codeStream.stackMax;
+               this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+               this.contents[codeAttributeOffset + 7] = (byte) max_stack;
+               int max_locals = this.codeStream.maxLocals;
+               this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+               this.contents[codeAttributeOffset + 9] = (byte) max_locals;
+               int code_length = this.codeStream.position;
+               this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+               this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+               this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+               this.contents[codeAttributeOffset + 13] = (byte) code_length;
+               // write the exception table
+               if (localContentsOffset + 50 >= this.contents.length) {
+                       resizeContents(50);
+               }
+
+               // write the exception table
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               // debug attributes
+               int codeAttributeAttributeOffset = localContentsOffset;
+               int attributesNumber = 0; // leave two bytes for the attribute_length
+               localContentsOffset += 2; // first we handle the linenumber attribute
+               if (localContentsOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+
+               this.contentsOffset = localContentsOffset;
+               if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
+                       if (problemLine == 0) {
+                               problemLine = Util.getLineNumber(binding.sourceStart(), startLineIndexes, 0, startLineIndexes.length-1);
+                       }
+                       attributesNumber += generateLineNumberAttribute(problemLine);
+               }
+
+               // then we do the local variable attribute
+               if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
+                       final boolean methodDeclarationIsStatic = this.codeStream.methodDeclaration.isStatic();
+                       attributesNumber += generateLocalVariableTableAttribute(code_length, methodDeclarationIsStatic, false);
+               }
+
+               if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0) {
+                       attributesNumber += generateStackMapTableAttribute(
+                                       binding,
+                                       code_length,
+                                       codeAttributeOffset,
+                                       max_locals,
+                                       false);
+               }
+
+               if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
+                       attributesNumber += generateStackMapAttribute(
+                                       binding,
+                                       code_length,
+                                       codeAttributeOffset,
+                                       max_locals,
+                                       false);
+               }
+
+               // update the number of attributes// ensure first that there is enough space available inside the localContents array
+               if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+               this.contents[codeAttributeAttributeOffset++] = (byte) (attributesNumber >> 8);
+               this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber;
+               // update the attribute length
+               int codeAttributeLength = this.contentsOffset - (codeAttributeOffset + 6);
+               this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+               this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+               this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+               this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method completes the creation of the code attribute by setting
+        * - the attribute_length
+        * - max_stack
+        * - max_locals
+        * - code_length
+        * - exception table
+        * - and debug attributes if necessary.
+        *
+        * @param binding org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding
+        * @param codeAttributeOffset <CODE>int</CODE>
+        */
+       public void completeCodeAttributeForSyntheticMethod(
+                       boolean hasExceptionHandlers,
+                       SyntheticMethodBinding binding,
+                       int codeAttributeOffset,
+                       int[] startLineIndexes) {
+               // reinitialize the contents with the byte modified by the code stream
+               this.contents = this.codeStream.bCodeStream;
+               int localContentsOffset = this.codeStream.classFileOffset;
+               // codeAttributeOffset is the position inside contents byte array before we started to write
+               // any information about the codeAttribute
+               // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
+               // to get the right position, 6 for the max_stack etc...
+               int max_stack = this.codeStream.stackMax;
+               this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+               this.contents[codeAttributeOffset + 7] = (byte) max_stack;
+               int max_locals = this.codeStream.maxLocals;
+               this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+               this.contents[codeAttributeOffset + 9] = (byte) max_locals;
+               int code_length = this.codeStream.position;
+               this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+               this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+               this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+               this.contents[codeAttributeOffset + 13] = (byte) code_length;
+               if ((localContentsOffset + 40) >= this.contents.length) {
+                       resizeContents(40);
+               }
+
+               boolean addStackMaps = (this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0;
+               if (hasExceptionHandlers) {
+                       // write the exception table
+                       ExceptionLabel[] exceptionLabels = this.codeStream.exceptionLabels;
+                       int exceptionHandlersCount = 0; // each label holds one handler per range (start/end contiguous)
+                       for (int i = 0, length = this.codeStream.exceptionLabelsCounter; i < length; i++) {
+                               exceptionHandlersCount += this.codeStream.exceptionLabels[i].getCount() / 2;
+                       }
+                       int exSize = exceptionHandlersCount * 8 + 2;
+                       if (exSize + localContentsOffset >= this.contents.length) {
+                               resizeContents(exSize);
+                       }
+                       // there is no exception table, so we need to offset by 2 the current offset and move
+                       // on the attribute generation
+                       this.contents[localContentsOffset++] = (byte) (exceptionHandlersCount >> 8);
+                       this.contents[localContentsOffset++] = (byte) exceptionHandlersCount;
+                       for (int i = 0, max = this.codeStream.exceptionLabelsCounter; i < max; i++) {
+                               ExceptionLabel exceptionLabel = exceptionLabels[i];
+                               if (exceptionLabel != null) {
+                                       int iRange = 0, maxRange = exceptionLabel.getCount();
+                                       if ((maxRange & 1) != 0) {
+                                               this.referenceBinding.scope.problemReporter().abortDueToInternalError(
+                                                               Messages.bind(Messages.abort_invalidExceptionAttribute, new String(binding.selector),
+                                                                               this.referenceBinding.scope.problemReporter().referenceContext));
+                                       }
+                                       while  (iRange < maxRange) {
+                                               int start = exceptionLabel.ranges[iRange++]; // even ranges are start positions
+                                               this.contents[localContentsOffset++] = (byte) (start >> 8);
+                                               this.contents[localContentsOffset++] = (byte) start;
+                                               int end = exceptionLabel.ranges[iRange++]; // odd ranges are end positions
+                                               this.contents[localContentsOffset++] = (byte) (end >> 8);
+                                               this.contents[localContentsOffset++] = (byte) end;
+                                               int handlerPC = exceptionLabel.position;
+                                               if (addStackMaps) {
+                                                       StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream;
+                                                       stackMapFrameCodeStream.addFramePosition(handlerPC);
+                                               }
+                                               this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
+                                               this.contents[localContentsOffset++] = (byte) handlerPC;
+                                               if (exceptionLabel.exceptionType == null) {
+                                                       // any exception handler
+                                                       this.contents[localContentsOffset++] = 0;
+                                                       this.contents[localContentsOffset++] = 0;
+                                               } else {
+                                                       int nameIndex;
+                                                       switch(exceptionLabel.exceptionType.id) {
+                                                               case T_null :
+                                                                       /* represents ClassNotFoundException, see class literal access*/
+                                                                       nameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
+                                                                       break;
+                                                               case T_long :
+                                                                       /* represents NoSuchFieldError, see switch table generation*/
+                                                                       nameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangNoSuchFieldErrorConstantPoolName);
+                                                                       break;
+                                                               default:
+                                                                       nameIndex = this.constantPool.literalIndexForType(exceptionLabel.exceptionType);
+                                                       }
+                                                       this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                                                       this.contents[localContentsOffset++] = (byte) nameIndex;
+                                               }
+                                       }
+                               }
+                       }
+               } else {
+                       // there is no exception table, so we need to offset by 2 the current offset and move
+                       // on the attribute generation
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+               }
+               // debug attributes
+               int codeAttributeAttributeOffset = localContentsOffset;
+               int attributesNumber = 0;
+               // leave two bytes for the attribute_length
+               localContentsOffset += 2;
+               if (localContentsOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+
+               this.contentsOffset = localContentsOffset;
+               // first we handle the linenumber attribute
+               if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
+                       int lineNumber = Util.getLineNumber(binding.sourceStart, startLineIndexes, 0, startLineIndexes.length-1);
+                       attributesNumber += generateLineNumberAttribute(lineNumber);
+               }
+               // then we do the local variable attribute
+               if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
+                       final boolean methodDeclarationIsStatic = binding.isStatic();
+                       attributesNumber += generateLocalVariableTableAttribute(code_length, methodDeclarationIsStatic, true);
+               }
+               if (addStackMaps) {
+                       attributesNumber += generateStackMapTableAttribute(binding, code_length, codeAttributeOffset, max_locals, false);
+               }
+
+               if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
+                       attributesNumber += generateStackMapAttribute(
+                                       binding,
+                                       code_length,
+                                       codeAttributeOffset,
+                                       max_locals,
+                                       false);
+               }
+
+               // update the number of attributes
+               // ensure first that there is enough space available inside the contents array
+               if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+               this.contents[codeAttributeAttributeOffset++] = (byte) (attributesNumber >> 8);
+               this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber;
+
+               // update the attribute length
+               int codeAttributeLength = this.contentsOffset - (codeAttributeOffset + 6);
+               this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+               this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+               this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+               this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method completes the creation of the code attribute by setting
+        * - the attribute_length
+        * - max_stack
+        * - max_locals
+        * - code_length
+        * - exception table
+        * - and debug attributes if necessary.
+        *
+        * @param binding org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding
+        * @param codeAttributeOffset <CODE>int</CODE>
+        */
+       public void completeCodeAttributeForSyntheticMethod(
+                       SyntheticMethodBinding binding,
+                       int codeAttributeOffset,
+                       int[] startLineIndexes) {
+
+               this.completeCodeAttributeForSyntheticMethod(
+                               false,
+                               binding,
+                               codeAttributeOffset,
+                               startLineIndexes);
+       }
+
+       private void completeArgumentAnnotationInfo(Argument[] arguments, List allAnnotationContexts) {
+               for (int i = 0, max = arguments.length; i < max; i++) {
+                       Argument argument = arguments[i];
+                       if ((argument.bits & ASTNode.HasTypeAnnotations) != 0) {
+                               argument.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_FORMAL_PARAMETER, i, allAnnotationContexts);
+                       }
+               }
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Complete the creation of a method info by setting up the number of attributes at the right offset.
+        *
+        * @param methodAttributeOffset <CODE>int</CODE>
+        * @param attributesNumber <CODE>int</CODE>
+        */
+       public void completeMethodInfo(
+                       MethodBinding binding,
+                       int methodAttributeOffset,
+                       int attributesNumber) {
+               
+               if ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) {
+                       List allTypeAnnotationContexts = new ArrayList();
+                       int invisibleTypeAnnotationsCounter = 0;
+                       int visibleTypeAnnotationsCounter = 0;
+                       AbstractMethodDeclaration methodDeclaration = binding.sourceMethod();
+                       if (methodDeclaration != null) {
+                               if ((methodDeclaration.bits & ASTNode.HasTypeAnnotations) != 0) {
+                                       Argument[] arguments = methodDeclaration.arguments;
+                                       if (arguments != null) {
+                                               completeArgumentAnnotationInfo(arguments, allTypeAnnotationContexts);
+                                       }
+                                       Receiver receiver = methodDeclaration.receiver;
+                                       if (receiver != null && (receiver.type.bits & ASTNode.HasTypeAnnotations) != 0) {
+                                               receiver.type.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_RECEIVER, allTypeAnnotationContexts);
+                                       }
+                               }
+                               Annotation[] annotations = methodDeclaration.annotations;
+                               if (annotations != null && !methodDeclaration.isClinit() && (methodDeclaration.isConstructor() || binding.returnType.id != T_void)) {
+                                       methodDeclaration.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_RETURN, allTypeAnnotationContexts);
+                               }
+                               if (!methodDeclaration.isConstructor() && !methodDeclaration.isClinit() && binding.returnType.id != T_void) {
+                                       MethodDeclaration declaration = (MethodDeclaration) methodDeclaration;
+                                       TypeReference typeReference = declaration.returnType;
+                                       if ((typeReference.bits & ASTNode.HasTypeAnnotations) != 0) {
+                                               typeReference.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_RETURN, allTypeAnnotationContexts);
+                                       }
+                               }
+                               TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
+                               if (thrownExceptions != null) {
+                                       for (int i = 0, max = thrownExceptions.length; i < max; i++) {
+                                               TypeReference thrownException = thrownExceptions[i];
+                                               thrownException.getAllAnnotationContexts(AnnotationTargetTypeConstants.THROWS, i, allTypeAnnotationContexts);
+                                       }
+                               }
+                               TypeParameter[] typeParameters = methodDeclaration.typeParameters();
+                               if (typeParameters != null) {
+                                       for (int i = 0, max = typeParameters.length; i < max; i++) {
+                                               TypeParameter typeParameter = typeParameters[i];
+                                               if ((typeParameter.bits & ASTNode.HasTypeAnnotations) != 0) {
+                                                       typeParameter.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER, i, allTypeAnnotationContexts);
+                                               }
+                                       }
+                               }
+                       } else if (binding.sourceLambda() != null) { // SyntheticMethodBinding, purpose : LambdaMethod.
+                               LambdaExpression lambda = binding.sourceLambda();
+                               if ((lambda.bits & ASTNode.HasTypeAnnotations) != 0) {
+                                       if (lambda.arguments != null)
+                                               completeArgumentAnnotationInfo(lambda.arguments, allTypeAnnotationContexts);
+                               }
+                       }
+                       int size = allTypeAnnotationContexts.size();
+                       if (size != 0) {
+                               AnnotationContext[] allTypeAnnotationContextsArray = new AnnotationContext[size];
+                               allTypeAnnotationContexts.toArray(allTypeAnnotationContextsArray);
+                               for (int j = 0, max2 = allTypeAnnotationContextsArray.length; j < max2; j++) {
+                                       AnnotationContext annotationContext = allTypeAnnotationContextsArray[j];
+                                       if ((annotationContext.visibility & AnnotationContext.INVISIBLE) != 0) {
+                                               invisibleTypeAnnotationsCounter++;
+                                       } else {
+                                               visibleTypeAnnotationsCounter++;
+                                       }
+                               }
+                               attributesNumber += generateRuntimeTypeAnnotations(
+                                               allTypeAnnotationContextsArray,
+                                               visibleTypeAnnotationsCounter,
+                                               invisibleTypeAnnotationsCounter);
+                       }
+               }
+               if ((this.produceAttributes & ClassFileConstants.ATTR_METHOD_PARAMETERS) != 0) {
+                       attributesNumber += generateMethodParameters(binding);
+               }
+               // update the number of attributes
+               this.contents[methodAttributeOffset++] = (byte) (attributesNumber >> 8);
+               this.contents[methodAttributeOffset] = (byte) attributesNumber;
+       }
+       
+       private void dumpLocations(int[] locations) {
+               if (locations == null) {
+                       // no type path
+                       if (this.contentsOffset + 1 >= this.contents.length) {
+                               resizeContents(1);
+                       }
+                       this.contents[this.contentsOffset++] = (byte) 0;
+               } else {
+                       int length = locations.length;
+                       if (this.contentsOffset + length >= this.contents.length) {
+                               resizeContents(length + 1);
+                       }
+                       this.contents[this.contentsOffset++] = (byte) (locations.length / 2);
+                       for (int i = 0; i < length; i++) {
+                               this.contents[this.contentsOffset++] = (byte) locations[i];
+                       }
+               }
+       }
+       private void dumpTargetTypeContents(int targetType, AnnotationContext annotationContext) {
+               switch(targetType) {
+                       case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER :
+                       case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER :
+                               // parameter index
+                               this.contents[this.contentsOffset++] = (byte) annotationContext.info;
+                               break;
+
+                       case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_BOUND :
+                               // type_parameter_index
+                               this.contents[this.contentsOffset++] = (byte) annotationContext.info;
+                               // bound_index
+                               this.contents[this.contentsOffset++] = (byte) annotationContext.info2;
+                               break;                          
+                       case AnnotationTargetTypeConstants.FIELD :
+                       case AnnotationTargetTypeConstants.METHOD_RECEIVER :
+                       case AnnotationTargetTypeConstants.METHOD_RETURN :
+                                // target_info is empty_target
+                               break;
+                       case AnnotationTargetTypeConstants.METHOD_FORMAL_PARAMETER :
+                               // target_info is parameter index
+                               this.contents[this.contentsOffset++] = (byte) annotationContext.info;
+                               break;
+                               
+                       case AnnotationTargetTypeConstants.INSTANCEOF :
+                       case AnnotationTargetTypeConstants.NEW :
+                       case AnnotationTargetTypeConstants.EXCEPTION_PARAMETER :
+                       case AnnotationTargetTypeConstants.CONSTRUCTOR_REFERENCE :
+                       case AnnotationTargetTypeConstants.METHOD_REFERENCE :
+                               // bytecode offset for new/instanceof/method_reference
+                               // exception table entry index for exception_parameter
+                               this.contents[this.contentsOffset++] = (byte) (annotationContext.info >> 8);
+                               this.contents[this.contentsOffset++] = (byte) annotationContext.info;
+                               break;
+                       case AnnotationTargetTypeConstants.CAST :
+                               // bytecode offset
+                               this.contents[this.contentsOffset++] = (byte) (annotationContext.info >> 8);
+                               this.contents[this.contentsOffset++] = (byte) annotationContext.info;
+                               this.contents[this.contentsOffset++] = (byte) annotationContext.info2;
+                               break;
+                               
+                       case AnnotationTargetTypeConstants.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT :
+                       case AnnotationTargetTypeConstants.METHOD_INVOCATION_TYPE_ARGUMENT :
+                       case AnnotationTargetTypeConstants.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT :
+                       case AnnotationTargetTypeConstants.METHOD_REFERENCE_TYPE_ARGUMENT :
+                               // bytecode offset
+                               this.contents[this.contentsOffset++] = (byte) (annotationContext.info >> 8);
+                               this.contents[this.contentsOffset++] = (byte) annotationContext.info;
+                               // type_argument_index 
+                               this.contents[this.contentsOffset++] = (byte) annotationContext.info2;
+                               break;
+                               
+                       case AnnotationTargetTypeConstants.CLASS_EXTENDS :
+                       case AnnotationTargetTypeConstants.THROWS :                     
+                               // For CLASS_EXTENDS - info is supertype index (-1 = superclass)
+                               // For THROWS - info is exception table index
+                               this.contents[this.contentsOffset++] = (byte) (annotationContext.info >> 8);
+                               this.contents[this.contentsOffset++] = (byte) annotationContext.info;
+                               break;
+                               
+                       case AnnotationTargetTypeConstants.LOCAL_VARIABLE :
+                       case AnnotationTargetTypeConstants.RESOURCE_VARIABLE :
+                               int localVariableTableOffset = this.contentsOffset;
+                               LocalVariableBinding localVariable = annotationContext.variableBinding;
+                               int actualSize = 0;
+                               int initializationCount = localVariable.initializationCount;
+                               actualSize += 6 * initializationCount;
+                               // reserve enough space
+                               if (this.contentsOffset + actualSize >= this.contents.length) {
+                                       resizeContents(actualSize);
+                               }
+                               this.contentsOffset += 2;
+                               int numberOfEntries = 0;
+                               for (int j = 0; j < initializationCount; j++) {
+                                       int startPC = localVariable.initializationPCs[j << 1];
+                                       int endPC = localVariable.initializationPCs[(j << 1) + 1];
+                                       if (startPC != endPC) { // only entries for non zero length
+                                               // now we can safely add the local entry
+                                               numberOfEntries++;
+                                               this.contents[this.contentsOffset++] = (byte) (startPC >> 8);
+                                               this.contents[this.contentsOffset++] = (byte) startPC;
+                                               int length = endPC - startPC;
+                                               this.contents[this.contentsOffset++] = (byte) (length >> 8);
+                                               this.contents[this.contentsOffset++] = (byte) length;
+                                               int resolvedPosition = localVariable.resolvedPosition;
+                                               this.contents[this.contentsOffset++] = (byte) (resolvedPosition >> 8);
+                                               this.contents[this.contentsOffset++] = (byte) resolvedPosition;
+                                       }
+                               }
+                               this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+                               this.contents[localVariableTableOffset] = (byte) numberOfEntries;
+                               break;
+                       case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_BOUND :
+                               this.contents[this.contentsOffset++] = (byte) annotationContext.info;
+                               this.contents[this.contentsOffset++] = (byte) annotationContext.info2;
+                               break;
+               }
+       }
+
+
+
+       /**
+        * INTERNAL USE-ONLY
+        * This methods returns a char[] representing the file name of the receiver
+        *
+        * @return char[]
+        */
+       public char[] fileName() {
+               return this.constantPool.UTF8Cache.returnKeyFor(2);
+       }
+
+       private void generateAnnotation(Annotation annotation, int currentOffset) {
+               int startingContentsOffset = currentOffset;
+               if (this.contentsOffset + 4 >= this.contents.length) {
+                       resizeContents(4);
+               }
+               TypeBinding annotationTypeBinding = annotation.resolvedType;
+               if (annotationTypeBinding == null) {
+                       this.contentsOffset = startingContentsOffset;
+                       return;
+               }
+               if (annotationTypeBinding.isMemberType()) {
+                       this.recordInnerClasses(annotationTypeBinding);
+               }
+               final int typeIndex = this.constantPool.literalIndex(annotationTypeBinding.signature());
+               this.contents[this.contentsOffset++] = (byte) (typeIndex >> 8);
+               this.contents[this.contentsOffset++] = (byte) typeIndex;
+               if (annotation instanceof NormalAnnotation) {
+                       NormalAnnotation normalAnnotation = (NormalAnnotation) annotation;
+                       MemberValuePair[] memberValuePairs = normalAnnotation.memberValuePairs;
+                       int memberValuePairOffset = this.contentsOffset;
+                       if (memberValuePairs != null) {
+                               int memberValuePairsCount = 0;
+                               int memberValuePairsLengthPosition = this.contentsOffset;
+                               this.contentsOffset+=2; // leave space to fill in the pair count later
+                               int resetPosition = this.contentsOffset;
+                               final int memberValuePairsLength = memberValuePairs.length;
+                               loop: for (int i = 0; i < memberValuePairsLength; i++) {
+                                       MemberValuePair memberValuePair = memberValuePairs[i];
+                                       if (this.contentsOffset + 2 >= this.contents.length) {
+                                               resizeContents(2);
+                                       }
+                                       final int elementNameIndex = this.constantPool.literalIndex(memberValuePair.name);
+                                       this.contents[this.contentsOffset++] = (byte) (elementNameIndex >> 8);
+                                       this.contents[this.contentsOffset++] = (byte) elementNameIndex;
+                                       MethodBinding methodBinding = memberValuePair.binding;
+                                       if (methodBinding == null) {
+                                               this.contentsOffset = resetPosition;
+                                       } else {
+                                               try {
+                                                       generateElementValue(memberValuePair.value, methodBinding.returnType, startingContentsOffset);
+                                                       if (this.contentsOffset == memberValuePairOffset) {
+                                                               // ignore all annotation values
+//                                                             this.contentsOffset = resetPosition;
+                                                               this.contents[this.contentsOffset++]=0;
+                                                               this.contents[this.contentsOffset++]=0;
+                                                               break loop;
+                                                       }
+                                                       memberValuePairsCount++;
+                                                       resetPosition = this.contentsOffset;
+                                               } catch(ClassCastException e) {
+                                                       this.contentsOffset = resetPosition;
+                                               } catch(ShouldNotImplement e) {
+                                                       this.contentsOffset = resetPosition;
+                                               }
+                                       }
+                               }
+                               this.contents[memberValuePairsLengthPosition++] = (byte) (memberValuePairsCount >> 8);
+                               this.contents[memberValuePairsLengthPosition++] = (byte) memberValuePairsCount;
+                       } else {
+                               this.contents[this.contentsOffset++] = 0;
+                               this.contents[this.contentsOffset++] = 0;
+                       }
+               } else if (annotation instanceof SingleMemberAnnotation) {
+                       SingleMemberAnnotation singleMemberAnnotation = (SingleMemberAnnotation) annotation;
+                       // this is a single member annotation (one member value)
+                       int memberValuePairCount = 0; // will not get to 1 if there is a problem with the annotation value
+                       int memberValuePairLengthPosition = this.contentsOffset;
+                       this.contentsOffset+=2;// leave space to fill in the pair count later
+                       if (this.contentsOffset + 2 >= this.contents.length) {
+                               resizeContents(2);
+                       }
+                       final int elementNameIndex = this.constantPool.literalIndex(VALUE);
+                       int resetPosition = this.contentsOffset;
+                       this.contents[this.contentsOffset++] = (byte) (elementNameIndex >> 8);
+                       this.contents[this.contentsOffset++] = (byte) elementNameIndex;
+                       MethodBinding methodBinding = singleMemberAnnotation.memberValuePairs()[0].binding;
+                       if (methodBinding == null) {
+                               this.contentsOffset = resetPosition;
+                       } else {
+                               int memberValuePairOffset = this.contentsOffset;
+                               try {
+                                       generateElementValue(singleMemberAnnotation.memberValue, methodBinding.returnType, memberValuePairOffset);
+                                       if (this.contentsOffset == memberValuePairOffset) {
+                                               // ignore annotation value
+                                               this.contentsOffset = resetPosition;
+                                       } else {
+                                               memberValuePairCount++;
+                                               resetPosition = this.contentsOffset;
+                                       }
+                               } catch(ClassCastException e) {
+                                       this.contentsOffset = resetPosition;
+                               } catch(ShouldNotImplement e) {
+                                       this.contentsOffset = resetPosition;
+                               }
+                       }
+                       this.contents[memberValuePairLengthPosition++] = (byte) (memberValuePairCount >> 8);
+                       this.contents[memberValuePairLengthPosition++] = (byte) memberValuePairCount;
+               } else {
+                       // this is a marker annotation (no member value pairs)
+                       this.contents[this.contentsOffset++] = 0;
+                       this.contents[this.contentsOffset++] = 0;
+               }
+       }
+
+       private int generateAnnotationDefaultAttribute(AnnotationMethodDeclaration declaration, int attributeOffset) {
+               int attributesNumber = 0;
+               // add an annotation default attribute
+               int annotationDefaultNameIndex =
+                       this.constantPool.literalIndex(AttributeNamesConstants.AnnotationDefaultName);
+               if (this.contentsOffset + 6 >= this.contents.length) {
+                       resizeContents(6);
+               }
+               this.contents[this.contentsOffset++] = (byte) (annotationDefaultNameIndex >> 8);
+               this.contents[this.contentsOffset++] = (byte) annotationDefaultNameIndex;
+               int attributeLengthOffset = this.contentsOffset;
+               this.contentsOffset += 4;
+               generateElementValue(declaration.defaultValue, declaration.binding.returnType, attributeOffset);
+               if (this.contentsOffset != attributeOffset) {
+                       int attributeLength = this.contentsOffset - attributeLengthOffset - 4;
+                       this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+                       this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+                       this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+                       this.contents[attributeLengthOffset++] = (byte) attributeLength;
+                       attributesNumber++;
+               }
+               return attributesNumber;
+       }
+       /**
+        * INTERNAL USE-ONLY
+        * That method generates the header of a code attribute.
+        * - the index inside the constant pool for the attribute name ("Code")
+        * - leave some space for attribute_length(4), max_stack(2), max_locals(2), code_length(4).
+        */
+       public void generateCodeAttributeHeader() {
+               if (this.contentsOffset + 20 >= this.contents.length) {
+                       resizeContents(20);
+               }
+               int constantValueNameIndex =
+                       this.constantPool.literalIndex(AttributeNamesConstants.CodeName);
+               this.contents[this.contentsOffset++] = (byte) (constantValueNameIndex >> 8);
+               this.contents[this.contentsOffset++] = (byte) constantValueNameIndex;
+               // leave space for attribute_length(4), max_stack(2), max_locals(2), code_length(4)
+               this.contentsOffset += 12;
+       }
+       
+       private int generateConstantValueAttribute(Constant fieldConstant, FieldBinding fieldBinding, int fieldAttributeOffset) {
+               int localContentsOffset = this.contentsOffset;
+               int attributesNumber = 1;
+               if (localContentsOffset + 8 >= this.contents.length) {
+                       resizeContents(8);
+               }
+               // Now we generate the constant attribute corresponding to the fieldBinding
+               int constantValueNameIndex =
+                       this.constantPool.literalIndex(AttributeNamesConstants.ConstantValueName);
+               this.contents[localContentsOffset++] = (byte) (constantValueNameIndex >> 8);
+               this.contents[localContentsOffset++] = (byte) constantValueNameIndex;
+               // The attribute length = 2 in case of a constantValue attribute
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 2;
+               // Need to add the constant_value_index
+               switch (fieldConstant.typeID()) {
+                       case T_boolean :
+                               int booleanValueIndex =
+                                       this.constantPool.literalIndex(fieldConstant.booleanValue() ? 1 : 0);
+                               this.contents[localContentsOffset++] = (byte) (booleanValueIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) booleanValueIndex;
+                               break;
+                       case T_byte :
+                       case T_char :
+                       case T_int :
+                       case T_short :
+                               int integerValueIndex =
+                                       this.constantPool.literalIndex(fieldConstant.intValue());
+                               this.contents[localContentsOffset++] = (byte) (integerValueIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) integerValueIndex;
+                               break;
+                       case T_float :
+                               int floatValueIndex =
+                                       this.constantPool.literalIndex(fieldConstant.floatValue());
+                               this.contents[localContentsOffset++] = (byte) (floatValueIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) floatValueIndex;
+                               break;
+                       case T_double :
+                               int doubleValueIndex =
+                                       this.constantPool.literalIndex(fieldConstant.doubleValue());
+                               this.contents[localContentsOffset++] = (byte) (doubleValueIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) doubleValueIndex;
+                               break;
+                       case T_long :
+                               int longValueIndex =
+                                       this.constantPool.literalIndex(fieldConstant.longValue());
+                               this.contents[localContentsOffset++] = (byte) (longValueIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) longValueIndex;
+                               break;
+                       case T_JavaLangString :
+                               int stringValueIndex =
+                                       this.constantPool.literalIndex(
+                                               ((StringConstant) fieldConstant).stringValue());
+                               if (stringValueIndex == -1) {
+                                       if (!this.creatingProblemType) {
+                                               // report an error and abort: will lead to a problem type classfile creation
+                                               TypeDeclaration typeDeclaration = this.referenceBinding.scope.referenceContext;
+                                               FieldDeclaration[] fieldDecls = typeDeclaration.fields;
+                                               int max = fieldDecls == null ? 0 : fieldDecls.length;
+                                               for (int i = 0; i < max; i++) {
+                                                       if (fieldDecls[i].binding == fieldBinding) {
+                                                               // problem should abort
+                                                               typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit(
+                                                                       fieldDecls[i]);
+                                                       }
+                                               }
+                                       } else {
+                                               // already inside a problem type creation : no constant for this field
+                                               this.contentsOffset = fieldAttributeOffset;
+                                               attributesNumber = 0;
+                                       }
+                               } else {
+                                       this.contents[localContentsOffset++] = (byte) (stringValueIndex >> 8);
+                                       this.contents[localContentsOffset++] = (byte) stringValueIndex;
+                               }
+               }
+               this.contentsOffset = localContentsOffset;
+               return attributesNumber;
+       }
+       private int generateDeprecatedAttribute() {
+               int localContentsOffset = this.contentsOffset;
+               if (localContentsOffset + 6 >= this.contents.length) {
+                       resizeContents(6);
+               }
+               int deprecatedAttributeNameIndex =
+                       this.constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
+               this.contents[localContentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
+               this.contents[localContentsOffset++] = (byte) deprecatedAttributeNameIndex;
+               // the length of a deprecated attribute is equals to 0
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contentsOffset = localContentsOffset;
+               return 1;
+       }
+       private void generateElementValue(
+                       Expression defaultValue,
+                       TypeBinding memberValuePairReturnType,
+                       int attributeOffset) {
+               Constant constant = defaultValue.constant;
+               TypeBinding defaultValueBinding = defaultValue.resolvedType;
+               if (defaultValueBinding == null) {
+                       this.contentsOffset = attributeOffset;
+               } else {
+                       if (defaultValueBinding.isMemberType()) {
+                               this.recordInnerClasses(defaultValueBinding);
+                       }
+                       if (memberValuePairReturnType.isMemberType()) {
+                               this.recordInnerClasses(memberValuePairReturnType);
+                       }
+                       if (memberValuePairReturnType.isArrayType() && !defaultValueBinding.isArrayType()) {
+                               // automatic wrapping
+                               if (this.contentsOffset + 3 >= this.contents.length) {
+                                       resizeContents(3);
+                               }
+                               this.contents[this.contentsOffset++] = (byte) '[';
+                               this.contents[this.contentsOffset++] = (byte) 0;
+                               this.contents[this.contentsOffset++] = (byte) 1;
+                       }
+                       if (constant != null && constant != Constant.NotAConstant) {
+                               generateElementValue(attributeOffset, defaultValue, constant, memberValuePairReturnType.leafComponentType());
+                       } else {
+                               generateElementValueForNonConstantExpression(defaultValue, attributeOffset, defaultValueBinding);
+                       }
+               }
+       }
+       /**
+        * @param attributeOffset
+        */
+       private void generateElementValue(int attributeOffset, Expression defaultValue, Constant constant, TypeBinding binding) {
+               if (this.contentsOffset + 3 >= this.contents.length) {
+                       resizeContents(3);
+               }
+               switch (binding.id) {
+                       case T_boolean :
+                               this.contents[this.contentsOffset++] = (byte) 'Z';
+                               int booleanValueIndex =
+                                       this.constantPool.literalIndex(constant.booleanValue() ? 1 : 0);
+                               this.contents[this.contentsOffset++] = (byte) (booleanValueIndex >> 8);
+                               this.contents[this.contentsOffset++] = (byte) booleanValueIndex;
+                               break;
+                       case T_byte :
+                               this.contents[this.contentsOffset++] = (byte) 'B';
+                               int integerValueIndex =
+                                       this.constantPool.literalIndex(constant.intValue());
+                               this.contents[this.contentsOffset++] = (byte) (integerValueIndex >> 8);
+                               this.contents[this.contentsOffset++] = (byte) integerValueIndex;
+                               break;
+                       case T_char :
+                               this.contents[this.contentsOffset++] = (byte) 'C';
+                               integerValueIndex =
+                                       this.constantPool.literalIndex(constant.intValue());
+                               this.contents[this.contentsOffset++] = (byte) (integerValueIndex >> 8);
+                               this.contents[this.contentsOffset++] = (byte) integerValueIndex;
+                               break;
+                       case T_int :
+                               this.contents[this.contentsOffset++] = (byte) 'I';
+                               integerValueIndex =
+                                       this.constantPool.literalIndex(constant.intValue());
+                               this.contents[this.contentsOffset++] = (byte) (integerValueIndex >> 8);
+                               this.contents[this.contentsOffset++] = (byte) integerValueIndex;
+                               break;
+                       case T_short :
+                               this.contents[this.contentsOffset++] = (byte) 'S';
+                               integerValueIndex =
+                                       this.constantPool.literalIndex(constant.intValue());
+                               this.contents[this.contentsOffset++] = (byte) (integerValueIndex >> 8);
+                               this.contents[this.contentsOffset++] = (byte) integerValueIndex;
+                               break;
+                       case T_float :
+                               this.contents[this.contentsOffset++] = (byte) 'F';
+                               int floatValueIndex =
+                                       this.constantPool.literalIndex(constant.floatValue());
+                               this.contents[this.contentsOffset++] = (byte) (floatValueIndex >> 8);
+                               this.contents[this.contentsOffset++] = (byte) floatValueIndex;
+                               break;
+                       case T_double :
+                               this.contents[this.contentsOffset++] = (byte) 'D';
+                               int doubleValueIndex =
+                                       this.constantPool.literalIndex(constant.doubleValue());
+                               this.contents[this.contentsOffset++] = (byte) (doubleValueIndex >> 8);
+                               this.contents[this.contentsOffset++] = (byte) doubleValueIndex;
+                               break;
+                       case T_long :
+                               this.contents[this.contentsOffset++] = (byte) 'J';
+                               int longValueIndex =
+                                       this.constantPool.literalIndex(constant.longValue());
+                               this.contents[this.contentsOffset++] = (byte) (longValueIndex >> 8);
+                               this.contents[this.contentsOffset++] = (byte) longValueIndex;
+                               break;
+                       case T_JavaLangString :
+                               this.contents[this.contentsOffset++] = (byte) 's';
+                               int stringValueIndex =
+                                       this.constantPool.literalIndex(((StringConstant) constant).stringValue().toCharArray());
+                               if (stringValueIndex == -1) {
+                                       if (!this.creatingProblemType) {
+                                               // report an error and abort: will lead to a problem type classfile creation
+                                               TypeDeclaration typeDeclaration = this.referenceBinding.scope.referenceContext;
+                                               typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit(defaultValue);
+                                       } else {
+                                               // already inside a problem type creation : no attribute
+                                               this.contentsOffset = attributeOffset;
+                                       }
+                               } else {
+                                       this.contents[this.contentsOffset++] = (byte) (stringValueIndex >> 8);
+                                       this.contents[this.contentsOffset++] = (byte) stringValueIndex;
+                               }
+               }
+       }
+       
+       private void generateElementValueForNonConstantExpression(Expression defaultValue, int attributeOffset, TypeBinding defaultValueBinding) {
+               if (defaultValueBinding != null) {
+                       if (defaultValueBinding.isEnum()) {
+                               if (this.contentsOffset + 5 >= this.contents.length) {
+                                       resizeContents(5);
+                               }
+                               this.contents[this.contentsOffset++] = (byte) 'e';
+                               FieldBinding fieldBinding = null;
+                               if (defaultValue instanceof QualifiedNameReference) {
+                                       QualifiedNameReference nameReference = (QualifiedNameReference) defaultValue;
+                                       fieldBinding = (FieldBinding) nameReference.binding;
+                               } else if (defaultValue instanceof SingleNameReference) {
+                                       SingleNameReference nameReference = (SingleNameReference) defaultValue;
+                                       fieldBinding = (FieldBinding) nameReference.binding;
+                               } else {
+                                       this.contentsOffset = attributeOffset;
+                               }
+                               if (fieldBinding != null) {
+                                       final int enumConstantTypeNameIndex = this.constantPool.literalIndex(fieldBinding.type.signature());
+                                       final int enumConstantNameIndex = this.constantPool.literalIndex(fieldBinding.name);
+                                       this.contents[this.contentsOffset++] = (byte) (enumConstantTypeNameIndex >> 8);
+                                       this.contents[this.contentsOffset++] = (byte) enumConstantTypeNameIndex;
+                                       this.contents[this.contentsOffset++] = (byte) (enumConstantNameIndex >> 8);
+                                       this.contents[this.contentsOffset++] = (byte) enumConstantNameIndex;
+                               }
+                       } else if (defaultValueBinding.isAnnotationType()) {
+                               if (this.contentsOffset + 1 >= this.contents.length) {
+                                       resizeContents(1);
+                               }
+                               this.contents[this.contentsOffset++] = (byte) '@';
+                               generateAnnotation((Annotation) defaultValue, attributeOffset);
+                       } else if (defaultValueBinding.isArrayType()) {
+                               // array type
+                               if (this.contentsOffset + 3 >= this.contents.length) {
+                                       resizeContents(3);
+                               }
+                               this.contents[this.contentsOffset++] = (byte) '[';
+                               if (defaultValue instanceof ArrayInitializer) {
+                                       ArrayInitializer arrayInitializer = (ArrayInitializer) defaultValue;
+                                       int arrayLength = arrayInitializer.expressions != null ? arrayInitializer.expressions.length : 0;
+                                       this.contents[this.contentsOffset++] = (byte) (arrayLength >> 8);
+                                       this.contents[this.contentsOffset++] = (byte) arrayLength;
+                                       for (int i = 0; i < arrayLength; i++) {
+                                               generateElementValue(arrayInitializer.expressions[i], defaultValueBinding.leafComponentType(), attributeOffset);
+                                       }
+                               } else {
+                                       this.contentsOffset = attributeOffset;
+                               }
+                       } else {
+                               // class type
+                               if (this.contentsOffset + 3 >= this.contents.length) {
+                                       resizeContents(3);
+                               }
+                               this.contents[this.contentsOffset++] = (byte) 'c';
+                               if (defaultValue instanceof ClassLiteralAccess) {
+                                       ClassLiteralAccess classLiteralAccess = (ClassLiteralAccess) defaultValue;
+                                       final int classInfoIndex = this.constantPool.literalIndex(classLiteralAccess.targetType.signature());
+                                       this.contents[this.contentsOffset++] = (byte) (classInfoIndex >> 8);
+                                       this.contents[this.contentsOffset++] = (byte) classInfoIndex;
+                               } else {
+                                       this.contentsOffset = attributeOffset;
+                               }
+                       }
+               } else {
+                       this.contentsOffset = attributeOffset;
+               }
+       }
+
+       private int generateEnclosingMethodAttribute() {
+               int localContentsOffset = this.contentsOffset;
+               // add enclosing method attribute (1.5 mode only)
+               if (localContentsOffset + 10 >= this.contents.length) {
+                       resizeContents(10);
+               }
+               int enclosingMethodAttributeNameIndex =
+                       this.constantPool.literalIndex(AttributeNamesConstants.EnclosingMethodName);
+               this.contents[localContentsOffset++] = (byte) (enclosingMethodAttributeNameIndex >> 8);
+               this.contents[localContentsOffset++] = (byte) enclosingMethodAttributeNameIndex;
+               // the length of a signature attribute is equals to 2
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 4;
+
+               int enclosingTypeIndex = this.constantPool.literalIndexForType(this.referenceBinding.enclosingType().constantPoolName());
+               this.contents[localContentsOffset++] = (byte) (enclosingTypeIndex >> 8);
+               this.contents[localContentsOffset++] = (byte) enclosingTypeIndex;
+               byte methodIndexByte1 = 0;
+               byte methodIndexByte2 = 0;
+               if (this.referenceBinding instanceof LocalTypeBinding) {
+                       MethodBinding methodBinding = ((LocalTypeBinding) this.referenceBinding).enclosingMethod;
+                       if (methodBinding != null) {
+                               int enclosingMethodIndex = this.constantPool.literalIndexForNameAndType(methodBinding.selector, methodBinding.signature(this));
+                               methodIndexByte1 = (byte) (enclosingMethodIndex >> 8);
+                               methodIndexByte2 = (byte) enclosingMethodIndex;
+                       }
+               }
+               this.contents[localContentsOffset++] = methodIndexByte1;
+               this.contents[localContentsOffset++] = methodIndexByte2;
+               this.contentsOffset = localContentsOffset;
+               return 1;
+       }
+       private int generateExceptionsAttribute(ReferenceBinding[] thrownsExceptions) {
+               int localContentsOffset = this.contentsOffset;
+               int length = thrownsExceptions.length;
+               int exSize = 8 + length * 2;
+               if (exSize + this.contentsOffset >= this.contents.length) {
+                       resizeContents(exSize);
+               }
+               int exceptionNameIndex =
+                       this.constantPool.literalIndex(AttributeNamesConstants.ExceptionsName);
+               this.contents[localContentsOffset++] = (byte) (exceptionNameIndex >> 8);
+               this.contents[localContentsOffset++] = (byte) exceptionNameIndex;
+               // The attribute length = length * 2 + 2 in case of a exception attribute
+               int attributeLength = length * 2 + 2;
+               this.contents[localContentsOffset++] = (byte) (attributeLength >> 24);
+               this.contents[localContentsOffset++] = (byte) (attributeLength >> 16);
+               this.contents[localContentsOffset++] = (byte) (attributeLength >> 8);
+               this.contents[localContentsOffset++] = (byte) attributeLength;
+               this.contents[localContentsOffset++] = (byte) (length >> 8);
+               this.contents[localContentsOffset++] = (byte) length;
+               for (int i = 0; i < length; i++) {
+                       int exceptionIndex = this.constantPool.literalIndexForType(thrownsExceptions[i]);
+                       this.contents[localContentsOffset++] = (byte) (exceptionIndex >> 8);
+                       this.contents[localContentsOffset++] = (byte) exceptionIndex;
+               }
+               this.contentsOffset = localContentsOffset;
+               return 1;
+       }
+       private int generateHierarchyInconsistentAttribute() {
+               int localContentsOffset = this.contentsOffset;
+               // add an attribute for inconsistent hierarchy
+               if (localContentsOffset + 6 >= this.contents.length) {
+                       resizeContents(6);
+               }
+               int inconsistentHierarchyNameIndex =
+                       this.constantPool.literalIndex(AttributeNamesConstants.InconsistentHierarchy);
+               this.contents[localContentsOffset++] = (byte) (inconsistentHierarchyNameIndex >> 8);
+               this.contents[localContentsOffset++] = (byte) inconsistentHierarchyNameIndex;
+               // the length of an inconsistent hierarchy attribute is equals to 0
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contentsOffset = localContentsOffset;
+               return 1;
+       }
+       private int generateInnerClassAttribute(int numberOfInnerClasses, ReferenceBinding[] innerClasses) {
+               int localContentsOffset = this.contentsOffset;
+               // Generate the inner class attribute
+               int exSize = 8 * numberOfInnerClasses + 8;
+               if (exSize + localContentsOffset >= this.contents.length) {
+                       resizeContents(exSize);
+               }
+               // Now we now the size of the attribute and the number of entries
+               // attribute name
+               int attributeNameIndex =
+                       this.constantPool.literalIndex(AttributeNamesConstants.InnerClassName);
+               this.contents[localContentsOffset++] = (byte) (attributeNameIndex >> 8);
+               this.contents[localContentsOffset++] = (byte) attributeNameIndex;
+               int value = (numberOfInnerClasses << 3) + 2;
+               this.contents[localContentsOffset++] = (byte) (value >> 24);
+               this.contents[localContentsOffset++] = (byte) (value >> 16);
+               this.contents[localContentsOffset++] = (byte) (value >> 8);
+               this.contents[localContentsOffset++] = (byte) value;
+               this.contents[localContentsOffset++] = (byte) (numberOfInnerClasses >> 8);
+               this.contents[localContentsOffset++] = (byte) numberOfInnerClasses;
+               for (int i = 0; i < numberOfInnerClasses; i++) {
+                       ReferenceBinding innerClass = innerClasses[i];
+                       int accessFlags = innerClass.getAccessFlags();
+                       int innerClassIndex = this.constantPool.literalIndexForType(innerClass.constantPoolName());
+                       // inner class index
+                       this.contents[localContentsOffset++] = (byte) (innerClassIndex >> 8);
+                       this.contents[localContentsOffset++] = (byte) innerClassIndex;
+                       // outer class index: anonymous and local have no outer class index
+                       if (innerClass.isMemberType()) {
+                               // member or member of local
+                               int outerClassIndex = this.constantPool.literalIndexForType(innerClass.enclosingType().constantPoolName());
+                               this.contents[localContentsOffset++] = (byte) (outerClassIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) outerClassIndex;
+                       } else {
+                               // equals to 0 if the innerClass is not a member type
+                               this.contents[localContentsOffset++] = 0;
+                               this.contents[localContentsOffset++] = 0;
+                       }
+                       // name index
+                       if (!innerClass.isAnonymousType()) {
+                               int nameIndex = this.constantPool.literalIndex(innerClass.sourceName());
+                               this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) nameIndex;
+                       } else {
+                               // equals to 0 if the innerClass is an anonymous type
+                               this.contents[localContentsOffset++] = 0;
+                               this.contents[localContentsOffset++] = 0;
+                       }
+                       // access flag
+                       if (innerClass.isAnonymousType()) {
+                               accessFlags &= ~ClassFileConstants.AccFinal;
+                       } else if (innerClass.isMemberType() && innerClass.isInterface()) {
+                               accessFlags |= ClassFileConstants.AccStatic; // implicitely static
+                       }
+                       this.contents[localContentsOffset++] = (byte) (accessFlags >> 8);
+                       this.contents[localContentsOffset++] = (byte) accessFlags;
+               }
+               this.contentsOffset = localContentsOffset;
+               return 1;
+       }
+
+       private int generateBootstrapMethods(List functionalExpressionList) {
+               /* See JVM spec 4.7.21
+                  The BootstrapMethods attribute has the following format:
+                  BootstrapMethods_attribute {
+                     u2 attribute_name_index;
+                     u4 attribute_length;
+                     u2 num_bootstrap_methods;
+                     {   u2 bootstrap_method_ref;
+                         u2 num_bootstrap_arguments;
+                         u2 bootstrap_arguments[num_bootstrap_arguments];
+                     } bootstrap_methods[num_bootstrap_methods];
+                }
+               */
+               // Record inner classes for MethodHandles$Lookup
+               ReferenceBinding methodHandlesLookup = this.referenceBinding.scope.getJavaLangInvokeMethodHandlesLookup();
+               if (methodHandlesLookup == null) return 0; // skip bootstrap section, class path problem already reported, just avoid NPE.
+               recordInnerClasses(methodHandlesLookup); // Should be done, it's what javac does also
+               ReferenceBinding javaLangInvokeLambdaMetafactory = this.referenceBinding.scope.getJavaLangInvokeLambdaMetafactory(); 
+               
+               // Depending on the complexity of the expression it may be necessary to use the altMetafactory() rather than the metafactory()
+               int indexForMetaFactory = 0;
+               int indexForAltMetaFactory = 0;
+
+               int numberOfBootstraps = functionalExpressionList.size();
+               int localContentsOffset = this.contentsOffset;
+               // Generate the boot strap attribute - since we are only making lambdas and
+               // functional expressions, we know the size ahead of time - this less general
+               // than the full invokedynamic scope, but fine for Java 8
+               
+               final int contentsEntries = 10;
+               int exSize = contentsEntries * numberOfBootstraps + 8;
+               if (exSize + localContentsOffset >= this.contents.length) {
+                       resizeContents(exSize);
+               }
+               
+               int attributeNameIndex =
+                       this.constantPool.literalIndex(AttributeNamesConstants.BootstrapMethodsName);
+               this.contents[localContentsOffset++] = (byte) (attributeNameIndex >> 8);
+               this.contents[localContentsOffset++] = (byte) attributeNameIndex;
+               // leave space for attribute_length and remember where to insert it
+               int attributeLengthPosition = localContentsOffset;
+               localContentsOffset += 4;
+               this.contents[localContentsOffset++] = (byte) (numberOfBootstraps >> 8);
+               this.contents[localContentsOffset++] = (byte) numberOfBootstraps;
+               for (int i = 0; i < numberOfBootstraps; i++) {
+                       FunctionalExpression functional = (FunctionalExpression) functionalExpressionList.get(i);
+                       MethodBinding [] bridges = functional.getRequiredBridges();
+                       TypeBinding[] markerInterfaces = null;
+                       if (functional instanceof LambdaExpression && 
+                                  (((markerInterfaces=((LambdaExpression)functional).getMarkerInterfaces()) != null) ||
+                                       ((LambdaExpression)functional).isSerializable) ||
+                                       bridges != null) {
+                               
+                               LambdaExpression lambdaEx = (LambdaExpression)functional;
+                               // may need even more space
+                               int extraSpace = 2; // at least 2 more than when the normal metafactory is used, for the bitflags entry
+                               if (markerInterfaces != null) {
+                                       // 2 for the marker interface list size then 2 per marker interface index
+                                       extraSpace += (2 + 2 * markerInterfaces.length);
+                               }
+                               if (bridges != null) {
+                                       // 2 for bridge count then 2 per bridge method type.
+                                       extraSpace += (2 + 2 * bridges.length);
+                               }
+                               if (extraSpace + contentsEntries + localContentsOffset >= this.contents.length) {
+                                       resizeContents(extraSpace + contentsEntries);
+                               } 
+                               
+                               if (indexForAltMetaFactory == 0) {
+                                       indexForAltMetaFactory = 
+                                               this.constantPool.literalIndexForMethodHandle(ClassFileConstants.MethodHandleRefKindInvokeStatic, javaLangInvokeLambdaMetafactory, 
+                                               ConstantPool.ALTMETAFACTORY, ConstantPool.JAVA_LANG_INVOKE_LAMBDAMETAFACTORY_ALTMETAFACTORY_SIGNATURE, false);
+                               }
+                               this.contents[localContentsOffset++] = (byte) (indexForAltMetaFactory >> 8);
+                               this.contents[localContentsOffset++] = (byte) indexForAltMetaFactory;
+                               
+                               // u2 num_bootstrap_arguments
+                               this.contents[localContentsOffset++] = 0;
+                               this.contents[localContentsOffset++] = (byte) (4 + (markerInterfaces==null?0:1+markerInterfaces.length) + 
+                                                                                                  (bridges == null ? 0 : 1 + bridges.length));
+                               
+                               int functionalDescriptorIndex = this.constantPool.literalIndexForMethodType(functional.descriptor.original().signature());
+                               this.contents[localContentsOffset++] = (byte) (functionalDescriptorIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) functionalDescriptorIndex;
+       
+                               int methodHandleIndex = this.constantPool.literalIndexForMethodHandle(functional.binding.original()); // Speak of " implementation" (erased) version here, adaptations described below.
+                               this.contents[localContentsOffset++] = (byte) (methodHandleIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) methodHandleIndex;
+       
+                               char [] instantiatedSignature = functional.descriptor.signature();
+                               int methodTypeIndex = this.constantPool.literalIndexForMethodType(instantiatedSignature);
+                               this.contents[localContentsOffset++] = (byte) (methodTypeIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) methodTypeIndex;
+
+                               int bitflags = 0;
+                               if (lambdaEx.isSerializable) {
+                                       bitflags |= ClassFileConstants.FLAG_SERIALIZABLE;
+                               }
+                               if (markerInterfaces!=null) {
+                                       bitflags |= ClassFileConstants.FLAG_MARKERS;
+                               }
+                               if (bridges != null) {
+                                       bitflags |= ClassFileConstants.FLAG_BRIDGES;
+                               }
+                               int indexForBitflags = this.constantPool.literalIndex(bitflags);
+                               
+                               this.contents[localContentsOffset++] = (byte)(indexForBitflags>>8);
+                               this.contents[localContentsOffset++] = (byte)(indexForBitflags);
+                               
+                               if (markerInterfaces != null) {
+                                       int markerInterfaceCountIndex =  this.constantPool.literalIndex(markerInterfaces.length);
+                                       this.contents[localContentsOffset++] = (byte)(markerInterfaceCountIndex>>8);
+                                       this.contents[localContentsOffset++] = (byte)(markerInterfaceCountIndex);
+                                       for (int m = 0, maxm = markerInterfaces.length; m < maxm; m++) {
+                                               int classTypeIndex = this.constantPool.literalIndexForType(markerInterfaces[m]);
+                                               this.contents[localContentsOffset++] = (byte)(classTypeIndex>>8);
+                                               this.contents[localContentsOffset++] = (byte)(classTypeIndex);
+                                       }                                       
+                               }
+                               if (bridges != null) {
+                                       int bridgeCountIndex =  this.constantPool.literalIndex(bridges.length);
+                                       this.contents[localContentsOffset++] = (byte) (bridgeCountIndex >> 8);
+                                       this.contents[localContentsOffset++] = (byte) (bridgeCountIndex);
+                                       for (int m = 0, maxm = bridges.length; m < maxm; m++) {
+                                               char [] bridgeSignature = bridges[m].signature();
+                                               int bridgeMethodTypeIndex = this.constantPool.literalIndexForMethodType(bridgeSignature);
+                                               this.contents[localContentsOffset++] = (byte) (bridgeMethodTypeIndex >> 8);
+                                               this.contents[localContentsOffset++] = (byte) bridgeMethodTypeIndex;
+                                       }                                       
+                               }
+                       } else {
+                               if (indexForMetaFactory == 0) {
+                                       indexForMetaFactory = this.constantPool.literalIndexForMethodHandle(ClassFileConstants.MethodHandleRefKindInvokeStatic, javaLangInvokeLambdaMetafactory, 
+                                                       ConstantPool.METAFACTORY, ConstantPool.JAVA_LANG_INVOKE_LAMBDAMETAFACTORY_METAFACTORY_SIGNATURE, false);
+                               }
+                               this.contents[localContentsOffset++] = (byte) (indexForMetaFactory >> 8);
+                               this.contents[localContentsOffset++] = (byte) indexForMetaFactory;
+                               
+                               // u2 num_bootstrap_arguments
+                               this.contents[localContentsOffset++] = 0;
+                               this.contents[localContentsOffset++] = (byte) 3;
+                               
+                               int functionalDescriptorIndex = this.constantPool.literalIndexForMethodType(functional.descriptor.original().signature());
+                               this.contents[localContentsOffset++] = (byte) (functionalDescriptorIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) functionalDescriptorIndex;
+       
+                               int methodHandleIndex = this.constantPool.literalIndexForMethodHandle(functional.binding.original()); // Speak of " implementation" (erased) version here, adaptations described below.
+                               this.contents[localContentsOffset++] = (byte) (methodHandleIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) methodHandleIndex;
+       
+                               char [] instantiatedSignature = functional.descriptor.signature();
+                               int methodTypeIndex = this.constantPool.literalIndexForMethodType(instantiatedSignature);
+                               this.contents[localContentsOffset++] = (byte) (methodTypeIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) methodTypeIndex;                          
+                       }
+               }
+
+               int attributeLength = localContentsOffset - attributeLengthPosition - 4;
+               this.contents[attributeLengthPosition++] = (byte) (attributeLength >> 24);
+               this.contents[attributeLengthPosition++] = (byte) (attributeLength >> 16);
+               this.contents[attributeLengthPosition++] = (byte) (attributeLength >> 8);
+               this.contents[attributeLengthPosition++] = (byte) attributeLength;
+               this.contentsOffset = localContentsOffset;
+               return 1;
+       }
+       private int generateLineNumberAttribute() {
+               int localContentsOffset = this.contentsOffset;
+               int attributesNumber = 0;
+               /* Create and add the line number attribute (used for debugging)
+                * Build the pairs of:
+                *      (bytecodePC lineNumber)
+                * according to the table of start line indexes and the pcToSourceMap table
+                * contained into the codestream
+                */
+               int[] pcToSourceMapTable;
+               if (((pcToSourceMapTable = this.codeStream.pcToSourceMap) != null)
+                       && (this.codeStream.pcToSourceMapSize != 0)) {
+                       int lineNumberNameIndex =
+                               this.constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+                       if (localContentsOffset + 8 >= this.contents.length) {
+                               resizeContents(8);
+                       }
+                       this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+                       this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
+                       int lineNumberTableOffset = localContentsOffset;
+                       localContentsOffset += 6;
+                       // leave space for attribute_length and line_number_table_length
+                       int numberOfEntries = 0;
+                       int length = this.codeStream.pcToSourceMapSize;
+                       for (int i = 0; i < length;) {
+                               // write the entry
+                               if (localContentsOffset + 4 >= this.contents.length) {
+                                       resizeContents(4);
+                               }
+                               int pc = pcToSourceMapTable[i++];
+                               this.contents[localContentsOffset++] = (byte) (pc >> 8);
+                               this.contents[localContentsOffset++] = (byte) pc;
+                               int lineNumber = pcToSourceMapTable[i++];
+                               this.contents[localContentsOffset++] = (byte) (lineNumber >> 8);
+                               this.contents[localContentsOffset++] = (byte) lineNumber;
+                               numberOfEntries++;
+                       }
+                       // now we change the size of the line number attribute
+                       int lineNumberAttr_length = numberOfEntries * 4 + 2;
+                       this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
+                       this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
+                       this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
+                       this.contents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
+                       this.contents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
+                       this.contents[lineNumberTableOffset++] = (byte) numberOfEntries;
+                       attributesNumber = 1;
+               }
+               this.contentsOffset = localContentsOffset;
+               return attributesNumber;
+       }
+       // this is used for problem and synthetic methods
+       private int generateLineNumberAttribute(int problemLine) {
+               int localContentsOffset = this.contentsOffset;
+               if (localContentsOffset + 12 >= this.contents.length) {
+                       resizeContents(12);
+               }
+               /* Create and add the line number attribute (used for debugging)
+                * Build the pairs of:
+                * (bytecodePC lineNumber)
+                * according to the table of start line indexes and the pcToSourceMap table
+                * contained into the codestream
+                */
+               int lineNumberNameIndex =
+                       this.constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+               this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+               this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 6;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 1;
+               // first entry at pc = 0
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = (byte) (problemLine >> 8);
+               this.contents[localContentsOffset++] = (byte) problemLine;
+               // now we change the size of the line number attribute
+               this.contentsOffset = localContentsOffset;
+               return 1;
+       }
+       
+       private int generateLocalVariableTableAttribute(int code_length, boolean methodDeclarationIsStatic, boolean isSynthetic) {
+               int attributesNumber = 0;
+               int localContentsOffset = this.contentsOffset;
+               int numberOfEntries = 0;
+               int localVariableNameIndex =
+                       this.constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+               int maxOfEntries = 8 + 10 * (methodDeclarationIsStatic ? 0 : 1);
+               for (int i = 0; i < this.codeStream.allLocalsCounter; i++) {
+                       LocalVariableBinding localVariableBinding = this.codeStream.locals[i];
+                       maxOfEntries += 10 * localVariableBinding.initializationCount;
+               }
+               // reserve enough space
+               if (localContentsOffset + maxOfEntries >= this.contents.length) {
+                       resizeContents(maxOfEntries);
+               }
+               this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+               this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
+               int localVariableTableOffset = localContentsOffset;
+               // leave space for attribute_length and local_variable_table_length
+               localContentsOffset += 6;
+               int nameIndex;
+               int descriptorIndex;
+               SourceTypeBinding declaringClassBinding = null;
+               if (!methodDeclarationIsStatic && !isSynthetic) {
+                       numberOfEntries++;
+                       this.contents[localContentsOffset++] = 0; // the startPC for this is always 0
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = (byte) (code_length >> 8);
+                       this.contents[localContentsOffset++] = (byte) code_length;
+                       nameIndex = this.constantPool.literalIndex(ConstantPool.This);
+                       this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                       this.contents[localContentsOffset++] = (byte) nameIndex;
+                       declaringClassBinding = (SourceTypeBinding) 
+                                       (this.codeStream.methodDeclaration != null ? this.codeStream.methodDeclaration.binding.declaringClass : this.codeStream.lambdaExpression.binding.declaringClass);
+                       descriptorIndex =
+                               this.constantPool.literalIndex(
+                                       declaringClassBinding.signature());
+                       this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+                       this.contents[localContentsOffset++] = (byte) descriptorIndex;
+                       this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0
+                       this.contents[localContentsOffset++] = 0;
+               }
+               // used to remember the local variable with a generic type
+               int genericLocalVariablesCounter = 0;
+               LocalVariableBinding[] genericLocalVariables = null;
+               int numberOfGenericEntries = 0;
+
+               for (int i = 0, max = this.codeStream.allLocalsCounter; i < max; i++) {
+                       LocalVariableBinding localVariable = this.codeStream.locals[i];
+                       int initializationCount = localVariable.initializationCount;
+                       if (initializationCount == 0) continue;
+                       if (localVariable.declaration == null) continue;
+                       final TypeBinding localVariableTypeBinding = localVariable.type;
+                       boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable();
+                       if (isParameterizedType) {
+                               if (genericLocalVariables == null) {
+                                       // we cannot have more than max locals
+                                       genericLocalVariables = new LocalVariableBinding[max];
+                               }
+                               genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
+                       }
+                       for (int j = 0; j < initializationCount; j++) {
+                               int startPC = localVariable.initializationPCs[j << 1];
+                               int endPC = localVariable.initializationPCs[(j << 1) + 1];
+                               if (startPC != endPC) { // only entries for non zero length
+                                       if (endPC == -1) {
+                                               localVariable.declaringScope.problemReporter().abortDueToInternalError(
+                                                               Messages.bind(Messages.abort_invalidAttribute, new String(localVariable.name)),
+                                                               (ASTNode) localVariable.declaringScope.methodScope().referenceContext);
+                                       }
+                                       if (isParameterizedType) {
+                                               numberOfGenericEntries++;
+                                       }
+                                       // now we can safely add the local entry
+                                       numberOfEntries++;
+                                       this.contents[localContentsOffset++] = (byte) (startPC >> 8);
+                                       this.contents[localContentsOffset++] = (byte) startPC;
+                                       int length = endPC - startPC;
+                                       this.contents[localContentsOffset++] = (byte) (length >> 8);
+                                       this.contents[localContentsOffset++] = (byte) length;
+                                       nameIndex = this.constantPool.literalIndex(localVariable.name);
+                                       this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                                       this.contents[localContentsOffset++] = (byte) nameIndex;
+                                       descriptorIndex = this.constantPool.literalIndex(localVariableTypeBinding.signature());
+                                       this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+                                       this.contents[localContentsOffset++] = (byte) descriptorIndex;
+                                       int resolvedPosition = localVariable.resolvedPosition;
+                                       this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+                                       this.contents[localContentsOffset++] = (byte) resolvedPosition;
+                               }
+                       }
+               }
+               int value = numberOfEntries * 10 + 2;
+               this.contents[localVariableTableOffset++] = (byte) (value >> 24);
+               this.contents[localVariableTableOffset++] = (byte) (value >> 16);
+               this.contents[localVariableTableOffset++] = (byte) (value >> 8);
+               this.contents[localVariableTableOffset++] = (byte) value;
+               this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+               this.contents[localVariableTableOffset] = (byte) numberOfEntries;
+               attributesNumber++;
+
+               final boolean currentInstanceIsGeneric =
+                       !methodDeclarationIsStatic
+                       && declaringClassBinding != null
+                       && declaringClassBinding.typeVariables != Binding.NO_TYPE_VARIABLES;
+               if (genericLocalVariablesCounter != 0 || currentInstanceIsGeneric) {
+                       // add the local variable type table attribute
+                       numberOfGenericEntries += (currentInstanceIsGeneric ? 1 : 0);
+                       maxOfEntries = 8 + numberOfGenericEntries * 10;
+                       // reserve enough space
+                       if (localContentsOffset + maxOfEntries >= this.contents.length) {
+                               resizeContents(maxOfEntries);
+                       }
+                       int localVariableTypeNameIndex =
+                               this.constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
+                       this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
+                       this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
+                       value = numberOfGenericEntries * 10 + 2;
+                       this.contents[localContentsOffset++] = (byte) (value >> 24);
+                       this.contents[localContentsOffset++] = (byte) (value >> 16);
+                       this.contents[localContentsOffset++] = (byte) (value >> 8);
+                       this.contents[localContentsOffset++] = (byte) value;
+                       this.contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
+                       this.contents[localContentsOffset++] = (byte) numberOfGenericEntries;
+                       if (currentInstanceIsGeneric) {
+                               this.contents[localContentsOffset++] = 0; // the startPC for this is always 0
+                               this.contents[localContentsOffset++] = 0;
+                               this.contents[localContentsOffset++] = (byte) (code_length >> 8);
+                               this.contents[localContentsOffset++] = (byte) code_length;
+                               nameIndex = this.constantPool.literalIndex(ConstantPool.This);
+                               this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) nameIndex;
+                               descriptorIndex = this.constantPool.literalIndex(declaringClassBinding.genericTypeSignature());
+                               this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) descriptorIndex;
+                               this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0
+                               this.contents[localContentsOffset++] = 0;
+                       }
+
+                       for (int i = 0; i < genericLocalVariablesCounter; i++) {
+                               LocalVariableBinding localVariable = genericLocalVariables[i];
+                               for (int j = 0; j < localVariable.initializationCount; j++) {
+                                       int startPC = localVariable.initializationPCs[j << 1];
+                                       int endPC = localVariable.initializationPCs[(j << 1) + 1];
+                                       if (startPC != endPC) {
+                                               // only entries for non zero length
+                                               // now we can safely add the local entry
+                                               this.contents[localContentsOffset++] = (byte) (startPC >> 8);
+                                               this.contents[localContentsOffset++] = (byte) startPC;
+                                               int length = endPC - startPC;
+                                               this.contents[localContentsOffset++] = (byte) (length >> 8);
+                                               this.contents[localContentsOffset++] = (byte) length;
+                                               nameIndex = this.constantPool.literalIndex(localVariable.name);
+                                               this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                                               this.contents[localContentsOffset++] = (byte) nameIndex;
+                                               descriptorIndex = this.constantPool.literalIndex(localVariable.type.genericTypeSignature());
+                                               this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+                                               this.contents[localContentsOffset++] = (byte) descriptorIndex;
+                                               int resolvedPosition = localVariable.resolvedPosition;
+                                               this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+                                               this.contents[localContentsOffset++] = (byte) resolvedPosition;
+                                       }
+                               }
+                       }
+                       attributesNumber++;
+               }
+               this.contentsOffset = localContentsOffset;
+               return attributesNumber;
+       }
+       /**
+        * INTERNAL USE-ONLY
+        * That method generates the attributes of a code attribute.
+        * They could be:
+        * - an exception attribute for each try/catch found inside the method
+        * - a deprecated attribute
+        * - a synthetic attribute for synthetic access methods
+        *
+        * It returns the number of attributes created for the code attribute.
+        *
+        * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding
+        * @return <CODE>int</CODE>
+        */
+       public int generateMethodInfoAttributes(MethodBinding methodBinding, List extraAttributes) { // AspectJ: extra parameter
+               // leave two bytes for the attribute_number
+               this.contentsOffset += 2;
+               if (this.contentsOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+               // now we can handle all the attribute for that method info:
+               // it could be:
+               // - a CodeAttribute
+               // - a ExceptionAttribute
+               // - a DeprecatedAttribute
+               // - a SyntheticAttribute
+
+               // Exception attribute
+               ReferenceBinding[] thrownsExceptions;
+               int attributesNumber = 0;
+               if ((thrownsExceptions = methodBinding.thrownExceptions) != Binding.NO_EXCEPTIONS) {
+                       // The method has a throw clause. So we need to add an exception attribute
+                       // check that there is enough space to write all the bytes for the exception attribute
+                       attributesNumber += generateExceptionsAttribute(thrownsExceptions);
+               }
+               if (methodBinding.isDeprecated()) {
+                       // Deprecated attribute
+                       attributesNumber += generateDeprecatedAttribute();
+               }
+               if (this.targetJDK < ClassFileConstants.JDK1_5) {
+                       if (methodBinding.isSynthetic()) {
+                               attributesNumber += generateSyntheticAttribute();
+                       }
+                       if (methodBinding.isVarargs()) {
+                               attributesNumber += generateVarargsAttribute();
+                       }
+               }
+               // add signature attribute
+               char[] genericSignature = methodBinding.genericSignature();
+               if (genericSignature != null) {
+                       attributesNumber += generateSignatureAttribute(genericSignature);
+               }
+               if (this.targetJDK >= ClassFileConstants.JDK1_4) {
+                       AbstractMethodDeclaration methodDeclaration = methodBinding.sourceMethod();
+                       if (methodBinding instanceof SyntheticMethodBinding) {
+                               SyntheticMethodBinding syntheticMethod = (SyntheticMethodBinding) methodBinding;
+                               if (syntheticMethod.purpose == SyntheticMethodBinding.SuperMethodAccess && CharOperation.equals(syntheticMethod.selector, syntheticMethod.targetMethod.selector))
+                                       methodDeclaration = ((SyntheticMethodBinding)methodBinding).targetMethod.sourceMethod();
+                       }
+                       if (methodDeclaration != null) {
+                               Annotation[] annotations = methodDeclaration.annotations;
+                               if (annotations != null) {
+                                       attributesNumber += generateRuntimeAnnotations(annotations, methodBinding.isConstructor() ? TagBits.AnnotationForConstructor : TagBits.AnnotationForMethod);
+                               }
+                               if ((methodBinding.tagBits & TagBits.HasParameterAnnotations) != 0) {
+                                       Argument[] arguments = methodDeclaration.arguments;
+                                       if (arguments != null) {
+                                               attributesNumber += generateRuntimeAnnotationsForParameters(arguments);
+                                       }
+                               }
+                       } else {
+                               LambdaExpression lambda = methodBinding.sourceLambda();
+                               if (lambda != null) {
+                                       if ((methodBinding.tagBits & TagBits.HasParameterAnnotations) != 0) {
+                                               Argument[] arguments = lambda.arguments();
+                                               if (arguments != null) {
+                                                       int parameterCount = methodBinding.parameters.length;
+                                                       int argumentCount = arguments.length;
+                                                       if (parameterCount > argumentCount) { // synthetics prefixed 
+                                                               int redShift = parameterCount - argumentCount;
+                                                               System.arraycopy(arguments, 0, arguments = new Argument[parameterCount], redShift, argumentCount);
+                                                               for (int i = 0; i < redShift; i++)
+                                                                       arguments[i] = new Argument(CharOperation.NO_CHAR, 0, null, 0);
+                                                       }
+                                                       attributesNumber += generateRuntimeAnnotationsForParameters(arguments);
+                                               }
+                                       }       
+                               }
+                       }
+               }
+               if ((methodBinding.tagBits & TagBits.HasMissingType) != 0) {
+                       this.missingTypes = methodBinding.collectMissingTypes(this.missingTypes);
+               }
+               // AspectJ Extension
+           if (extraAttributes != null) {
+             for (int i=0, len = extraAttributes.size(); i < len; i++) {
+                 IAttribute attribute = (IAttribute)extraAttributes.get(i);
+                 short nameIndex = (short)constantPool.literalIndex(attribute.getNameChars());
+                 writeToContents(attribute.getAllBytes(nameIndex,constantPool));
+                 attributesNumber++;
+             }
+           }
+           // End AspectJ Extension
+               return attributesNumber;
+       }
+       // AspectJ Extension - new method stub that can pass 3rd param
+       public int generateMethodInfoAttributes(MethodBinding methodBinding) {
+         return generateMethodInfoAttributes(methodBinding,(List)null);
+       }
+       // End AspectJ Extension
+       public int generateMethodInfoAttributes(MethodBinding methodBinding, AnnotationMethodDeclaration declaration) {
+               int attributesNumber = generateMethodInfoAttributes(methodBinding);
+               int attributeOffset = this.contentsOffset;
+               if ((declaration.modifiers & ClassFileConstants.AccAnnotationDefault) != 0) {
+                       // add an annotation default attribute
+                       attributesNumber += generateAnnotationDefaultAttribute(declaration, attributeOffset);
+               }
+               return attributesNumber;
+       }
+       /**
+        * INTERNAL USE-ONLY
+        * That method generates the header of a method info:
+        * The header consists in:
+        * - the access flags
+        * - the name index of the method name inside the constant pool
+        * - the descriptor index of the signature of the method inside the constant pool.
+        *
+        * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding
+        */
+       public void generateMethodInfoHeader(MethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding, methodBinding.modifiers);
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method generates the header of a method info:
+        * The header consists in:
+        * - the access flags
+        * - the name index of the method name inside the constant pool
+        * - the descriptor index of the signature of the method inside the constant pool.
+        *
+        * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding
+        * @param accessFlags the access flags
+        */
+       public void generateMethodInfoHeader(MethodBinding methodBinding, int accessFlags) {
+               // check that there is enough space to write all the bytes for the method info corresponding
+               // to the @methodBinding
+               this.methodCount++; // add one more method
+               if (this.contentsOffset + 10 >= this.contents.length) {
+                       resizeContents(10);
+               }
+               if (this.targetJDK < ClassFileConstants.JDK1_5) {
+                       // pre 1.5, synthetic is an attribute, not a modifier
+                       // pre 1.5, varargs is an attribute, not a modifier (-target jsr14 mode)
+                       accessFlags &= ~(ClassFileConstants.AccSynthetic | ClassFileConstants.AccVarargs);
+               }
+               if ((methodBinding.tagBits & TagBits.ClearPrivateModifier) != 0) {
+                       accessFlags &= ~ClassFileConstants.AccPrivate;
+               }
+               this.contents[this.contentsOffset++] = (byte) (accessFlags >> 8);
+               this.contents[this.contentsOffset++] = (byte) accessFlags;
+               int nameIndex = this.constantPool.literalIndex(methodBinding.selector);
+               this.contents[this.contentsOffset++] = (byte) (nameIndex >> 8);
+               this.contents[this.contentsOffset++] = (byte) nameIndex;
+               int descriptorIndex = this.constantPool.literalIndex(methodBinding.signature(this));
+               this.contents[this.contentsOffset++] = (byte) (descriptorIndex >> 8);
+               this.contents[this.contentsOffset++] = (byte) descriptorIndex;
+       }
+       
+       public void addSyntheticDeserializeLambda(SyntheticMethodBinding methodBinding, SyntheticMethodBinding[] syntheticMethodBindings ) {
+               generateMethodInfoHeader(methodBinding);
+               int methodAttributeOffset = this.contentsOffset;
+               // this will add exception attribute, synthetic attribute, deprecated attribute,...
+               int attributeNumber = generateMethodInfoAttributes(methodBinding);
+               // Code attribute
+               int codeAttributeOffset = this.contentsOffset;
+               attributeNumber++; // add code attribute
+               generateCodeAttributeHeader();
+               this.codeStream.init(this);
+               this.codeStream.generateSyntheticBodyForDeserializeLambda(methodBinding, syntheticMethodBindings);
+               completeCodeAttributeForSyntheticMethod(
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .getLineSeparatorPositions());
+               // update the number of attributes
+               if ((this.produceAttributes & ClassFileConstants.ATTR_METHOD_PARAMETERS) != 0) {
+                       attributeNumber += generateMethodParameters(methodBinding);
+               }
+               this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[methodAttributeOffset] = (byte) attributeNumber;
+       }       
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method generates the method info header of a clinit:
+        * The header consists in:
+        * - the access flags (always default access + static)
+        * - the name index of the method name (always <clinit>) inside the constant pool
+        * - the descriptor index of the signature (always ()V) of the method inside the constant pool.
+        */
+       public void generateMethodInfoHeaderForClinit() {
+               // check that there is enough space to write all the bytes for the method info corresponding
+               // to the @methodBinding
+               this.methodCount++; // add one more method
+               if (this.contentsOffset + 10 >= this.contents.length) {
+                       resizeContents(10);
+               }
+               this.contents[this.contentsOffset++] = (byte) ((ClassFileConstants.AccDefault | ClassFileConstants.AccStatic) >> 8);
+               this.contents[this.contentsOffset++] = (byte) (ClassFileConstants.AccDefault | ClassFileConstants.AccStatic);
+               int nameIndex = this.constantPool.literalIndex(ConstantPool.Clinit);
+               this.contents[this.contentsOffset++] = (byte) (nameIndex >> 8);
+               this.contents[this.contentsOffset++] = (byte) nameIndex;
+               int descriptorIndex =
+                       this.constantPool.literalIndex(ConstantPool.ClinitSignature);
+               this.contents[this.contentsOffset++] = (byte) (descriptorIndex >> 8);
+               this.contents[this.contentsOffset++] = (byte) descriptorIndex;
+               // We know that we won't get more than 1 attribute: the code attribute
+               this.contents[this.contentsOffset++] = 0;
+               this.contents[this.contentsOffset++] = 1;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for problem method infos that correspond to missing abstract methods.
+        * http://dev.eclipse.org/bugs/show_bug.cgi?id=3179
+        *
+        * @param methodDeclarations Array of all missing abstract methods
+        */
+       public void generateMissingAbstractMethods(MethodDeclaration[] methodDeclarations, CompilationResult compilationResult) {
+               if (methodDeclarations != null) {
+                       TypeDeclaration currentDeclaration = this.referenceBinding.scope.referenceContext;
+                       int typeDeclarationSourceStart = currentDeclaration.sourceStart();
+                       int typeDeclarationSourceEnd = currentDeclaration.sourceEnd();
+                       for (int i = 0, max = methodDeclarations.length; i < max; i++) {
+                               MethodDeclaration methodDeclaration = methodDeclarations[i];
+                               MethodBinding methodBinding = methodDeclaration.binding;
+                                String readableName = new String(methodBinding.readableName());
+                                CategorizedProblem[] problems = compilationResult.problems;
+                                int problemsCount = compilationResult.problemCount;
+                               for (int j = 0; j < problemsCount; j++) {
+                                       CategorizedProblem problem = problems[j];
+                                       if (problem != null
+                                                       && problem.getID() == IProblem.AbstractMethodMustBeImplemented
+                                                       && problem.getMessage().indexOf(readableName) != -1
+                                                       && problem.getSourceStart() >= typeDeclarationSourceStart
+                                                       && problem.getSourceEnd() <= typeDeclarationSourceEnd) {
+                                               // we found a match
+                                               addMissingAbstractProblemMethod(methodDeclaration, methodBinding, problem, compilationResult);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       private void generateMissingTypesAttribute() {
+               int initialSize = this.missingTypes.size();
+               int[] missingTypesIndexes = new int[initialSize];
+               int numberOfMissingTypes = 0;
+               if (initialSize > 1) {
+                       Collections.sort(this.missingTypes, new Comparator() {
+                               public int compare(Object o1, Object o2) {
+                                       TypeBinding typeBinding1 = (TypeBinding) o1;
+                                       TypeBinding typeBinding2 = (TypeBinding) o2;
+                                       return CharOperation.compareTo(typeBinding1.constantPoolName(), typeBinding2.constantPoolName());
+                               }
+                       });
+               }
+               int previousIndex = 0;
+               next: for (int i = 0; i < initialSize; i++) {
+                       int missingTypeIndex = this.constantPool.literalIndexForType((TypeBinding) this.missingTypes.get(i));
+                       if (previousIndex == missingTypeIndex) {
+                               continue next;
+                       }
+                       previousIndex = missingTypeIndex;
+                       missingTypesIndexes[numberOfMissingTypes++] = missingTypeIndex;
+               }
+               // we don't need to resize as we interate from 0 to numberOfMissingTypes when recording the indexes in the .class file
+               int attributeLength = numberOfMissingTypes * 2 + 2;
+               if (this.contentsOffset + attributeLength + 6 >= this.contents.length) {
+                       resizeContents(attributeLength + 6);
+               }
+               int missingTypesNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.MissingTypesName);
+               this.contents[this.contentsOffset++] = (byte) (missingTypesNameIndex >> 8);
+               this.contents[this.contentsOffset++] = (byte) missingTypesNameIndex;
+
+               // generate attribute length
+               this.contents[this.contentsOffset++] = (byte) (attributeLength >> 24);
+               this.contents[this.contentsOffset++] = (byte) (attributeLength >> 16);
+               this.contents[this.contentsOffset++] = (byte) (attributeLength >> 8);
+               this.contents[this.contentsOffset++] = (byte) attributeLength;
+
+               // generate number of missing types
+               this.contents[this.contentsOffset++] = (byte) (numberOfMissingTypes >> 8);
+               this.contents[this.contentsOffset++] = (byte) numberOfMissingTypes;
+               // generate entry for each missing type
+               for (int i = 0; i < numberOfMissingTypes; i++) {
+                       int missingTypeIndex = missingTypesIndexes[i];
+                       this.contents[this.contentsOffset++] = (byte) (missingTypeIndex >> 8);
+                       this.contents[this.contentsOffset++] = (byte) missingTypeIndex;
+               }
+       }
+
+       /**
+        * @param annotations
+        * @param targetMask allowed targets
+        * @return the number of attributes created while dumping the annotations in the .class file
+        */
+       private int generateRuntimeAnnotations(final Annotation[] annotations, final long targetMask) {
+               int attributesNumber = 0;
+               final int length = annotations.length;
+               int visibleAnnotationsCounter = 0;
+               int invisibleAnnotationsCounter = 0;
+               for (int i = 0; i < length; i++) {
+                       Annotation annotation;
+                       if ((annotation = annotations[i].getPersistibleAnnotation()) == null) continue; // already packaged into container.
+                       long annotationMask = annotation.resolvedType != null ? annotation.resolvedType.getAnnotationTagBits() & TagBits.AnnotationTargetMASK : 0;
+                       // AspectJ Extension: this prevents a Type targeting annotation being stashed on a
+                       // method representing an 'declare @type'. So don't enforce this restriction
+//                     if (annotationMask != 0 && (annotationMask & targetMask) == 0) continue;
+                       // AspectJ Extension: End
+                       if (annotation.isRuntimeInvisible() || annotation.isRuntimeTypeInvisible()) {
+                               invisibleAnnotationsCounter++;
+                       } else if (annotation.isRuntimeVisible() || annotation.isRuntimeTypeVisible()) {
+                               visibleAnnotationsCounter++;
+                       }
+               }
+
+               int annotationAttributeOffset = this.contentsOffset;
+               int constantPOffset = this.constantPool.currentOffset;
+               int constantPoolIndex = this.constantPool.currentIndex;
+               if (invisibleAnnotationsCounter != 0) {
+                       if (this.contentsOffset + 10 >= this.contents.length) {
+                               resizeContents(10);
+                       }
+                       int runtimeInvisibleAnnotationsAttributeNameIndex =
+                               this.constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleAnnotationsName);
+                       this.contents[this.contentsOffset++] = (byte) (runtimeInvisibleAnnotationsAttributeNameIndex >> 8);
+                       this.contents[this.contentsOffset++] = (byte) runtimeInvisibleAnnotationsAttributeNameIndex;
+                       int attributeLengthOffset = this.contentsOffset;
+                       this.contentsOffset += 4; // leave space for the attribute length
+
+                       int annotationsLengthOffset = this.contentsOffset;
+                       this.contentsOffset += 2; // leave space for the annotations length
+
+                       int counter = 0;
+                       loop: for (int i = 0; i < length; i++) {
+                               if (invisibleAnnotationsCounter == 0) break loop;
+                               Annotation annotation;
+                               if ((annotation = annotations[i].getPersistibleAnnotation()) == null) continue; // already packaged into container.
+                               long annotationMask = annotation.resolvedType != null ? annotation.resolvedType.getAnnotationTagBits() & TagBits.AnnotationTargetMASK : 0;
+                               // AspectJ Extension: this prevents a Type targeting annotation being stashed on a
+                               // method representing an 'declare @type'. So don't enforce this restriction
+//                             if (annotationMask != 0 && (annotationMask & targetMask) == 0) continue;
+                               // AspectJ Extension: end
+                               if (annotation.isRuntimeInvisible() || annotation.isRuntimeTypeInvisible()) {
+                                       int currentAnnotationOffset = this.contentsOffset;
+                                       generateAnnotation(annotation, currentAnnotationOffset);
+                                       invisibleAnnotationsCounter--;
+                                       if (this.contentsOffset != currentAnnotationOffset) {
+                                               counter++;
+                                       }
+                               }
+                       }
+                       if (counter != 0) {
+                               this.contents[annotationsLengthOffset++] = (byte) (counter >> 8);
+                               this.contents[annotationsLengthOffset++] = (byte) counter;
+
+                               int attributeLength = this.contentsOffset - attributeLengthOffset - 4;
+                               this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+                               this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+                               this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+                               this.contents[attributeLengthOffset++] = (byte) attributeLength;
+                               attributesNumber++;
+                       } else {
+                               this.contentsOffset = annotationAttributeOffset;
+                               // reset the constant pool to its state before the clinit
+                               this.constantPool.resetForAttributeName(AttributeNamesConstants.RuntimeInvisibleAnnotationsName, constantPoolIndex, constantPOffset);
+                       }
+               }
+
+               annotationAttributeOffset = this.contentsOffset;
+               constantPOffset = this.constantPool.currentOffset;
+               constantPoolIndex = this.constantPool.currentIndex;
+               if (visibleAnnotationsCounter != 0) {
+                       if (this.contentsOffset + 10 >= this.contents.length) {
+                               resizeContents(10);
+                       }
+                       int runtimeVisibleAnnotationsAttributeNameIndex =
+                               this.constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleAnnotationsName);
+                       this.contents[this.contentsOffset++] = (byte) (runtimeVisibleAnnotationsAttributeNameIndex >> 8);
+                       this.contents[this.contentsOffset++] = (byte) runtimeVisibleAnnotationsAttributeNameIndex;
+                       int attributeLengthOffset = this.contentsOffset;
+                       this.contentsOffset += 4; // leave space for the attribute length
+
+                       int annotationsLengthOffset = this.contentsOffset;
+                       this.contentsOffset += 2; // leave space for the annotations length
+
+                       int counter = 0;
+                       loop: for (int i = 0; i < length; i++) {
+                               if (visibleAnnotationsCounter == 0) break loop;
+                               Annotation annotation;
+                               if ((annotation = annotations[i].getPersistibleAnnotation()) == null) continue; // already packaged into container.
+                               long annotationMask = annotation.resolvedType != null ? annotation.resolvedType.getAnnotationTagBits() & TagBits.AnnotationTargetMASK : 0;
+                               // AspectJ Extension: this prevents a Type targeting annotation being stashed on a
+                               // method representing an 'declare @type'. So don't enforce this restriction
+//                             if (annotationMask != 0 && (annotationMask & targetMask) == 0) continue;
+                               // AspectJ Extension: end
+                               if (annotation.isRuntimeVisible() || annotation.isRuntimeTypeVisible()) {
+                                       visibleAnnotationsCounter--;
+                                       int currentAnnotationOffset = this.contentsOffset;
+                                       generateAnnotation(annotation, currentAnnotationOffset);
+                                       if (this.contentsOffset != currentAnnotationOffset) {
+                                               counter++;
+                                       }
+                               }
+                       }
+                       if (counter != 0) {
+                               this.contents[annotationsLengthOffset++] = (byte) (counter >> 8);
+                               this.contents[annotationsLengthOffset++] = (byte) counter;
+
+                               int attributeLength = this.contentsOffset - attributeLengthOffset - 4;
+                               this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+                               this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+                               this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+                               this.contents[attributeLengthOffset++] = (byte) attributeLength;
+                               attributesNumber++;
+                       } else {
+                               this.contentsOffset = annotationAttributeOffset;
+                               this.constantPool.resetForAttributeName(AttributeNamesConstants.RuntimeVisibleAnnotationsName, constantPoolIndex, constantPOffset);
+                       }
+               }
+               return attributesNumber;
+       }
+       
+       private int generateRuntimeAnnotationsForParameters(Argument[] arguments) {
+               final int argumentsLength = arguments.length;
+               final int VISIBLE_INDEX = 0;
+               final int INVISIBLE_INDEX = 1;
+               int invisibleParametersAnnotationsCounter = 0;
+               int visibleParametersAnnotationsCounter = 0;
+               int[][] annotationsCounters = new int[argumentsLength][2];
+               for (int i = 0; i < argumentsLength; i++) {
+                       Argument argument = arguments[i];
+                       Annotation[] annotations = argument.annotations;
+                       if (annotations != null) {
+                               for (int j = 0, max2 = annotations.length; j < max2; j++) {
+                                       Annotation annotation;
+                                       if ((annotation = annotations[j].getPersistibleAnnotation()) == null) continue; // already packaged into container.
+                                       long annotationMask = annotation.resolvedType != null ? annotation.resolvedType.getAnnotationTagBits() & TagBits.AnnotationTargetMASK : 0;
+                                       if (annotationMask != 0 && (annotationMask & TagBits.AnnotationForParameter) == 0) continue;
+                                       if (annotation.isRuntimeInvisible()) {
+                                               annotationsCounters[i][INVISIBLE_INDEX]++;
+                                               invisibleParametersAnnotationsCounter++;
+                                       } else if (annotation.isRuntimeVisible()) {
+                                               annotationsCounters[i][VISIBLE_INDEX]++;
+                                               visibleParametersAnnotationsCounter++;
+                                       }
+                               }
+                       }
+               }
+               int attributesNumber = 0;
+               int annotationAttributeOffset = this.contentsOffset;
+               if (invisibleParametersAnnotationsCounter != 0) {
+                       int globalCounter = 0;
+                       if (this.contentsOffset + 7 >= this.contents.length) {
+                               resizeContents(7);
+                       }
+                       int attributeNameIndex =
+                               this.constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleParameterAnnotationsName);
+                       this.contents[this.contentsOffset++] = (byte) (attributeNameIndex >> 8);
+                       this.contents[this.contentsOffset++] = (byte) attributeNameIndex;
+                       int attributeLengthOffset = this.contentsOffset;
+                       this.contentsOffset += 4; // leave space for the attribute length
+
+                       this.contents[this.contentsOffset++] = (byte) argumentsLength;
+                       for (int i = 0; i < argumentsLength; i++) {
+                               if (this.contentsOffset + 2 >= this.contents.length) {
+                                       resizeContents(2);
+                               }
+                               if (invisibleParametersAnnotationsCounter == 0) {
+                                       this.contents[this.contentsOffset++] = (byte) 0;
+                                       this.contents[this.contentsOffset++] = (byte) 0;
+                               } else {
+                                       final int numberOfInvisibleAnnotations = annotationsCounters[i][INVISIBLE_INDEX];
+                                       int invisibleAnnotationsOffset = this.contentsOffset;
+                                       // leave space for number of annotations
+                                       this.contentsOffset += 2;
+                                       int counter = 0;
+                                       if (numberOfInvisibleAnnotations != 0) {
+                                               Argument argument = arguments[i];
+                                               Annotation[] annotations = argument.annotations;
+                                               for (int j = 0, max = annotations.length; j < max; j++) {
+                                                       Annotation annotation;
+                                                       if ((annotation = annotations[j].getPersistibleAnnotation()) == null) continue; // already packaged into container.
+                                                       long annotationMask = annotation.resolvedType != null ? annotation.resolvedType.getAnnotationTagBits() & TagBits.AnnotationTargetMASK : 0;
+                                                       if (annotationMask != 0 && (annotationMask & TagBits.AnnotationForParameter) == 0) continue;
+                                                       if (annotation.isRuntimeInvisible()) {
+                                                               int currentAnnotationOffset = this.contentsOffset;
+                                                               generateAnnotation(annotation, currentAnnotationOffset);
+                                                               if (this.contentsOffset != currentAnnotationOffset) {
+                                                                       counter++;
+                                                                       globalCounter++;
+                                                               }
+                                                               invisibleParametersAnnotationsCounter--;
+                                                       }
+                                               }
+                                       }
+                                       this.contents[invisibleAnnotationsOffset++] = (byte) (counter >> 8);
+                                       this.contents[invisibleAnnotationsOffset] = (byte) counter;
+                               }
+                       }
+                       if (globalCounter != 0) {
+                               int attributeLength = this.contentsOffset - attributeLengthOffset - 4;
+                               this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+                               this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+                               this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+                               this.contents[attributeLengthOffset++] = (byte) attributeLength;
+                               attributesNumber++;
+                       } else {
+                               // if globalCounter is 0, this means that the code generation for all visible annotations failed
+                               this.contentsOffset = annotationAttributeOffset;
+                       }
+               }
+               if (visibleParametersAnnotationsCounter != 0) {
+                       int globalCounter = 0;
+                       if (this.contentsOffset + 7 >= this.contents.length) {
+                               resizeContents(7);
+                       }
+                       int attributeNameIndex =
+                               this.constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleParameterAnnotationsName);
+                       this.contents[this.contentsOffset++] = (byte) (attributeNameIndex >> 8);
+                       this.contents[this.contentsOffset++] = (byte) attributeNameIndex;
+                       int attributeLengthOffset = this.contentsOffset;
+                       this.contentsOffset += 4; // leave space for the attribute length
+
+                       this.contents[this.contentsOffset++] = (byte) argumentsLength;
+                       for (int i = 0; i < argumentsLength; i++) {
+                               if (this.contentsOffset + 2 >= this.contents.length) {
+                                       resizeContents(2);
+                               }
+                               if (visibleParametersAnnotationsCounter == 0) {
+                                       this.contents[this.contentsOffset++] = (byte) 0;
+                                       this.contents[this.contentsOffset++] = (byte) 0;
+                               } else {
+                                       final int numberOfVisibleAnnotations = annotationsCounters[i][VISIBLE_INDEX];
+                                       int visibleAnnotationsOffset = this.contentsOffset;
+                                       // leave space for number of annotations
+                                       this.contentsOffset += 2;
+                                       int counter = 0;
+                                       if (numberOfVisibleAnnotations != 0) {
+                                               Argument argument = arguments[i];
+                                               Annotation[] annotations = argument.annotations;
+                                               for (int j = 0, max = annotations.length; j < max; j++) {
+                                                       Annotation annotation;
+                                                       if ((annotation = annotations[j].getPersistibleAnnotation()) == null) continue; // already packaged into container.
+                                                       long annotationMask = annotation.resolvedType != null ? annotation.resolvedType.getAnnotationTagBits() & TagBits.AnnotationTargetMASK : 0;
+                                                       if (annotationMask != 0 && (annotationMask & TagBits.AnnotationForParameter) == 0) continue;
+                                                       if (annotation.isRuntimeVisible()) {
+                                                               int currentAnnotationOffset = this.contentsOffset;
+                                                               generateAnnotation(annotation, currentAnnotationOffset);
+                                                               if (this.contentsOffset != currentAnnotationOffset) {
+                                                                       counter++;
+                                                                       globalCounter++;
+                                                               }
+                                                               visibleParametersAnnotationsCounter--;
+                                                       }
+                                               }
+                                       }
+                                       this.contents[visibleAnnotationsOffset++] = (byte) (counter >> 8);
+                                       this.contents[visibleAnnotationsOffset] = (byte) counter;
+                               }
+                       }
+                       if (globalCounter != 0) {
+                               int attributeLength = this.contentsOffset - attributeLengthOffset - 4;
+                               this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+                               this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+                               this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+                               this.contents[attributeLengthOffset++] = (byte) attributeLength;
+                               attributesNumber++;
+                       } else {
+                               // if globalCounter is 0, this means that the code generation for all visible annotations failed
+                               this.contentsOffset = annotationAttributeOffset;
+                       }
+               }
+               return attributesNumber;
+       }
+       
+       /**
+        * @param annotationContexts the given annotation contexts
+        * @param visibleTypeAnnotationsNumber the given number of visible type annotations
+        * @param invisibleTypeAnnotationsNumber the given number of invisible type annotations
+        * @return the number of attributes created while dumping the annotations in the .class file
+        */
+       private int generateRuntimeTypeAnnotations(
+                       final AnnotationContext[] annotationContexts, 
+                       int visibleTypeAnnotationsNumber, 
+                       int invisibleTypeAnnotationsNumber) {
+               int attributesNumber = 0;
+               final int length = annotationContexts.length;
+
+               int visibleTypeAnnotationsCounter = visibleTypeAnnotationsNumber;
+               int invisibleTypeAnnotationsCounter = invisibleTypeAnnotationsNumber;
+               int annotationAttributeOffset = this.contentsOffset;
+               int constantPOffset = this.constantPool.currentOffset;
+               int constantPoolIndex = this.constantPool.currentIndex;
+               if (invisibleTypeAnnotationsCounter != 0) {
+                       if (this.contentsOffset + 10 >= this.contents.length) {
+                               resizeContents(10);
+                       }
+                       int runtimeInvisibleAnnotationsAttributeNameIndex =
+                               this.constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleTypeAnnotationsName);
+                       this.contents[this.contentsOffset++] = (byte) (runtimeInvisibleAnnotationsAttributeNameIndex >> 8);
+                       this.contents[this.contentsOffset++] = (byte) runtimeInvisibleAnnotationsAttributeNameIndex;
+                       int attributeLengthOffset = this.contentsOffset;
+                       this.contentsOffset += 4; // leave space for the attribute length
+
+                       int annotationsLengthOffset = this.contentsOffset;
+                       this.contentsOffset += 2; // leave space for the annotations length
+
+                       int counter = 0;
+                       loop: for (int i = 0; i < length; i++) {
+                               if (invisibleTypeAnnotationsCounter == 0) break loop;
+                               AnnotationContext annotationContext = annotationContexts[i];
+                               if ((annotationContext.visibility & AnnotationContext.INVISIBLE) != 0) {
+                                       int currentAnnotationOffset = this.contentsOffset;
+                                       generateTypeAnnotation(annotationContext, currentAnnotationOffset);
+                                       invisibleTypeAnnotationsCounter--;
+                                       if (this.contentsOffset != currentAnnotationOffset) {
+                                               counter++;
+                                       }
+                               }
+                       }
+                       if (counter != 0) {
+                               this.contents[annotationsLengthOffset++] = (byte) (counter >> 8);
+                               this.contents[annotationsLengthOffset++] = (byte) counter;
+
+                               int attributeLength = this.contentsOffset - attributeLengthOffset - 4;
+                               this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+                               this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+                               this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+                               this.contents[attributeLengthOffset++] = (byte) attributeLength;
+                               attributesNumber++;
+                       } else {
+                               this.contentsOffset = annotationAttributeOffset;
+                               // reset the constant pool to its state before the clinit
+                               this.constantPool.resetForAttributeName(AttributeNamesConstants.RuntimeInvisibleTypeAnnotationsName, constantPoolIndex, constantPOffset);
+                       }
+               }
+
+               annotationAttributeOffset = this.contentsOffset;
+               constantPOffset = this.constantPool.currentOffset;
+               constantPoolIndex = this.constantPool.currentIndex;
+               if (visibleTypeAnnotationsCounter != 0) {
+                       if (this.contentsOffset + 10 >= this.contents.length) {
+                               resizeContents(10);
+                       }
+                       int runtimeVisibleAnnotationsAttributeNameIndex =
+                               this.constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleTypeAnnotationsName);
+                       this.contents[this.contentsOffset++] = (byte) (runtimeVisibleAnnotationsAttributeNameIndex >> 8);
+                       this.contents[this.contentsOffset++] = (byte) runtimeVisibleAnnotationsAttributeNameIndex;
+                       int attributeLengthOffset = this.contentsOffset;
+                       this.contentsOffset += 4; // leave space for the attribute length
+
+                       int annotationsLengthOffset = this.contentsOffset;
+                       this.contentsOffset += 2; // leave space for the annotations length
+
+                       int counter = 0;
+                       loop: for (int i = 0; i < length; i++) {
+                               if (visibleTypeAnnotationsCounter == 0) break loop;
+                               AnnotationContext annotationContext = annotationContexts[i];
+                               if ((annotationContext.visibility & AnnotationContext.VISIBLE) != 0) {
+                                       visibleTypeAnnotationsCounter--;
+                                       int currentAnnotationOffset = this.contentsOffset;
+                                       generateTypeAnnotation(annotationContext, currentAnnotationOffset);
+                                       if (this.contentsOffset != currentAnnotationOffset) {
+                                               counter++;
+                                       }
+                               }
+                       }
+                       if (counter != 0) {
+                               this.contents[annotationsLengthOffset++] = (byte) (counter >> 8);
+                               this.contents[annotationsLengthOffset++] = (byte) counter;
+
+                               int attributeLength = this.contentsOffset - attributeLengthOffset - 4;
+                               this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+                               this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+                               this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+                               this.contents[attributeLengthOffset++] = (byte) attributeLength;
+                               attributesNumber++;
+                       } else {
+                               this.contentsOffset = annotationAttributeOffset;
+                               this.constantPool.resetForAttributeName(AttributeNamesConstants.RuntimeVisibleTypeAnnotationsName, constantPoolIndex, constantPOffset);
+                       }
+               }
+               return attributesNumber;
+       }
+
+       /**
+        * @param binding the given method binding
+        * @return the number of attributes created while dumping he method's parameters in the .class file (0 or 1)
+        */
+       private int generateMethodParameters(final MethodBinding binding) {
+               
+               int initialContentsOffset = this.contentsOffset;
+               int length = 0; // count of actual parameters
+               
+               AbstractMethodDeclaration methodDeclaration = binding.sourceMethod();
+               
+               boolean isConstructor = binding.isConstructor();
+               TypeBinding[] targetParameters = binding.parameters;
+               ReferenceBinding declaringClass = binding.declaringClass;
+
+               if (declaringClass.isEnum()) {
+                       if (isConstructor) { // insert String name,int ordinal
+                               length = writeArgumentName(ConstantPool.EnumName, ClassFileConstants.AccSynthetic, length);
+                               length = writeArgumentName(ConstantPool.EnumOrdinal, ClassFileConstants.AccSynthetic, length);
+                       } else if (CharOperation.equals(ConstantPool.ValueOf, binding.selector)) { // insert String name
+                               length = writeArgumentName(ConstantPool.Name, ClassFileConstants.AccMandated, length);
+                               targetParameters =  Binding.NO_PARAMETERS; // Override "unknown" synthetics below
+                       }
+               }
+
+               boolean needSynthetics = isConstructor && declaringClass.isNestedType();
+               if (needSynthetics) {
+                       // Take into account the synthetic argument names
+                       // This tracks JLS8, paragraph 8.8.9
+                       boolean anonymousWithLocalSuper = declaringClass.isAnonymousType() && declaringClass.superclass().isLocalType();
+                       boolean anonymousWithNestedSuper = declaringClass.isAnonymousType() && declaringClass.superclass().isNestedType();
+                       boolean isImplicitlyDeclared = ((! declaringClass.isPrivate()) || declaringClass.isAnonymousType()) && !anonymousWithLocalSuper;
+                       ReferenceBinding[] syntheticArgumentTypes = declaringClass.syntheticEnclosingInstanceTypes();
+                       if (syntheticArgumentTypes != null) {
+                               for (int i = 0, count = syntheticArgumentTypes.length; i < count; i++) {
+                                       // This behaviour tracks JLS 15.9.5.1
+                                       // This covers that the parameter ending up in a nested class must be mandated "on the way in", even if it
+                                       // isn't the first. The practical relevance of this is questionable, since the constructor call will be
+                                       // generated by the same constructor.
+                                       boolean couldForwardToMandated = anonymousWithNestedSuper ? declaringClass.superclass().enclosingType().equals(syntheticArgumentTypes[i]) : true;
+                                       int modifier = couldForwardToMandated && isImplicitlyDeclared ? ClassFileConstants.AccMandated : ClassFileConstants.AccSynthetic;
+                                       char[] name = CharOperation.concat(
+                                                       TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX,
+                                                       String.valueOf(i).toCharArray()); // cannot use depth, can be identical
+                                       length = writeArgumentName(name, modifier | ClassFileConstants.AccFinal, length);
+                               }
+                       }
+                       if (binding instanceof SyntheticMethodBinding) {
+                               targetParameters = ((SyntheticMethodBinding)binding).targetMethod.parameters;
+                               methodDeclaration = ((SyntheticMethodBinding)binding).targetMethod.sourceMethod();
+                       }
+               }
+               if (targetParameters != Binding.NO_PARAMETERS) {
+                       Argument[] arguments = null;
+                       if (methodDeclaration != null && methodDeclaration.arguments != null) {
+                               arguments = methodDeclaration.arguments;
+                       } else if (binding.sourceLambda() != null) { // SyntheticMethodBinding, purpose : LambdaMethod.
+                               arguments = binding.sourceLambda().arguments;
+                       }
+                       for (int i = 0, max = targetParameters.length, argumentsLength = arguments != null ? arguments.length : 0; i < max; i++) {
+                               if (argumentsLength > i && arguments[i] != null) {
+                                       Argument argument = arguments[i];
+                                       length = writeArgumentName(argument.name, argument.binding.modifiers, length);
+                               } else {
+                                       length = writeArgumentName(null, ClassFileConstants.AccSynthetic, length);
+                               }
+                       }
+               }
+               if (needSynthetics) {
+                       SyntheticArgumentBinding[] syntheticOuterArguments = declaringClass.syntheticOuterLocalVariables();
+                       int count = syntheticOuterArguments == null ? 0 : syntheticOuterArguments.length;
+                       for (int i = 0; i < count; i++) {
+                               length = writeArgumentName(syntheticOuterArguments[i].name, syntheticOuterArguments[i].modifiers  | ClassFileConstants.AccSynthetic, length);
+                       }
+                       // move the extra padding arguments of the synthetic constructor invocation to the end
+                       for (int i = targetParameters.length, extraLength = binding.parameters.length; i < extraLength; i++) {
+                               TypeBinding parameter = binding.parameters[i];
+                               length = writeArgumentName(parameter.constantPoolName(), ClassFileConstants.AccSynthetic, length);
+                       }
+               }
+
+               if (length > 0) {
+                       // so we actually output the parameter
+                       int attributeLength = 1 + 4 * length; // u1 for count, u2+u2 per parameter
+                       if (this.contentsOffset + 6 + attributeLength >= this.contents.length) {
+                               resizeContents(6 + attributeLength);
+                       }
+                       int methodParametersNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.MethodParametersName);
+                       this.contents[initialContentsOffset++] = (byte) (methodParametersNameIndex >> 8);
+                       this.contents[initialContentsOffset++] = (byte) methodParametersNameIndex;
+                       this.contents[initialContentsOffset++] = (byte) (attributeLength >> 24);
+                       this.contents[initialContentsOffset++] = (byte) (attributeLength >> 16);
+                       this.contents[initialContentsOffset++] = (byte) (attributeLength >> 8);
+                       this.contents[initialContentsOffset++] = (byte) attributeLength;
+                       this.contents[initialContentsOffset++] = (byte) length;
+                       return 1;
+               }
+               else {
+                       return 0;
+               }
+       }
+       private int writeArgumentName(char[] name, int modifiers, int oldLength) {
+               int ensureRoomForBytes = 4;
+               if (oldLength == 0) {
+                       // Make room for 
+                       ensureRoomForBytes += 7;
+                       this.contentsOffset += 7; // Make room for attribute header + count byte
+               }
+               if (this.contentsOffset + ensureRoomForBytes > this.contents.length) {
+                               resizeContents(ensureRoomForBytes);
+               }
+               int parameterNameIndex = name == null ? 0 : this.constantPool.literalIndex(name);
+               this.contents[this.contentsOffset++] = (byte) (parameterNameIndex >> 8);
+               this.contents[this.contentsOffset++] = (byte) parameterNameIndex;
+               int flags = modifiers & (ClassFileConstants.AccFinal | ClassFileConstants.AccSynthetic | ClassFileConstants.AccMandated);
+               this.contents[this.contentsOffset++] = (byte) (flags >> 8);
+               this.contents[this.contentsOffset++] = (byte) flags;
+               return oldLength + 1;
+       }
+
+       private int generateSignatureAttribute(char[] genericSignature) {
+               int localContentsOffset = this.contentsOffset;
+               if (localContentsOffset + 8 >= this.contents.length) {
+                       resizeContents(8);
+               }
+               int signatureAttributeNameIndex =
+                       this.constantPool.literalIndex(AttributeNamesConstants.SignatureName);
+               this.contents[localContentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
+               this.contents[localContentsOffset++] = (byte) signatureAttributeNameIndex;
+               // the length of a signature attribute is equals to 2
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 2;
+               int signatureIndex =
+                       this.constantPool.literalIndex(genericSignature);
+               this.contents[localContentsOffset++] = (byte) (signatureIndex >> 8);
+               this.contents[localContentsOffset++] = (byte) signatureIndex;
+               this.contentsOffset = localContentsOffset;
+               return 1;
+       }
+
+       private int generateSourceAttribute(String fullFileName) {
+               int localContentsOffset = this.contentsOffset;
+               // check that there is enough space to write all the bytes for the field info corresponding
+               // to the @fieldBinding
+               if (localContentsOffset + 8 >= this.contents.length) {
+                       resizeContents(8);
+               }
+               int sourceAttributeNameIndex =
+                       this.constantPool.literalIndex(AttributeNamesConstants.SourceName);
+               this.contents[localContentsOffset++] = (byte) (sourceAttributeNameIndex >> 8);
+               this.contents[localContentsOffset++] = (byte) sourceAttributeNameIndex;
+               // The length of a source file attribute is 2. This is a fixed-length
+               // attribute
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 2;
+               // write the source file name
+               int fileNameIndex = this.constantPool.literalIndex(fullFileName.toCharArray());
+               this.contents[localContentsOffset++] = (byte) (fileNameIndex >> 8);
+               this.contents[localContentsOffset++] = (byte) fileNameIndex;
+               this.contentsOffset = localContentsOffset;
+               return 1;
+       }
+       private int generateStackMapAttribute(
+                       MethodBinding methodBinding,
+                       int code_length,
+                       int codeAttributeOffset,
+                       int max_locals,
+                       boolean isClinit) {
+               int attributesNumber = 0;
+               int localContentsOffset = this.contentsOffset;
+               StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream;
+               stackMapFrameCodeStream.removeFramePosition(code_length);
+               if (stackMapFrameCodeStream.hasFramePositions()) {
+                       Map frames = new HashMap();
+                       List realFrames = traverse(isClinit ? null : methodBinding, max_locals, this.contents, codeAttributeOffset + 14, code_length, frames, isClinit);
+                       int numberOfFrames = realFrames.size();
+                       if (numberOfFrames > 1) {
+                               int stackMapTableAttributeOffset = localContentsOffset;
+                               // add the stack map table attribute
+                               if (localContentsOffset + 8 >= this.contents.length) {
+                                       resizeContents(8);
+                               }
+                               int stackMapAttributeNameIndex =
+                                       this.constantPool.literalIndex(AttributeNamesConstants.StackMapName);
+                               this.contents[localContentsOffset++] = (byte) (stackMapAttributeNameIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) stackMapAttributeNameIndex;
+
+                               int stackMapAttributeLengthOffset = localContentsOffset;
+                               // generate the attribute
+                               localContentsOffset += 4;
+                               if (localContentsOffset + 4 >= this.contents.length) {
+                                       resizeContents(4);
+                               }
+                               int numberOfFramesOffset = localContentsOffset;
+                               localContentsOffset += 2;
+                               if (localContentsOffset + 2 >= this.contents.length) {
+                                       resizeContents(2);
+                               }
+                               StackMapFrame currentFrame = (StackMapFrame) realFrames.get(0);
+                               for (int j = 1; j < numberOfFrames; j++) {
+                                       // select next frame
+                                       currentFrame = (StackMapFrame) realFrames.get(j);
+                                       // generate current frame
+                                       // need to find differences between the current frame and the previous frame
+                                       int frameOffset = currentFrame.pc;
+                                       // FULL_FRAME
+                                       if (localContentsOffset + 5 >= this.contents.length) {
+                                               resizeContents(5);
+                                       }
+                                       this.contents[localContentsOffset++] = (byte) (frameOffset >> 8);
+                                       this.contents[localContentsOffset++] = (byte) frameOffset;
+                                       int numberOfLocalOffset = localContentsOffset;
+                                       localContentsOffset += 2; // leave two spots for number of locals
+                                       int numberOfLocalEntries = 0;
+                                       int numberOfLocals = currentFrame.getNumberOfLocals();
+                                       int numberOfEntries = 0;
+                                       int localsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length;
+                                       for (int i = 0; i < localsLength && numberOfLocalEntries < numberOfLocals; i++) {
+                                               if (localContentsOffset + 3 >= this.contents.length) {
+                                                       resizeContents(3);
+                                               }
+                                               VerificationTypeInfo info = currentFrame.locals[i];
+                                               if (info == null) {
+                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
+                                               } else {
+                                                       switch(info.id()) {
+                                                               case T_boolean :
+                                                               case T_byte :
+                                                               case T_char :
+                                                               case T_int :
+                                                               case T_short :
+                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
+                                                                       break;
+                                                               case T_float :
+                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
+                                                                       break;
+                                                               case T_long :
+                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
+                                                                       i++;
+                                                                       break;
+                                                               case T_double :
+                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
+                                                                       i++;
+                                                                       break;
+                                                               case T_null :
+                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
+                                                                       break;
+                                                               default:
+                                                                       this.contents[localContentsOffset++] = (byte) info.tag;
+                                                               switch (info.tag) {
+                                                                       case VerificationTypeInfo.ITEM_UNINITIALIZED :
+                                                                               int offset = info.offset;
+                                                                               this.contents[localContentsOffset++] = (byte) (offset >> 8);
+                                                                               this.contents[localContentsOffset++] = (byte) offset;
+                                                                               break;
+                                                                       case VerificationTypeInfo.ITEM_OBJECT :
+                                                                               int indexForType = this.constantPool.literalIndexForType(info.constantPoolName());
+                                                                               this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
+                                                                               this.contents[localContentsOffset++] = (byte) indexForType;
+                                                               }
+                                                       }
+                                                       numberOfLocalEntries++;
+                                               }
+                                               numberOfEntries++;
+                                       }
+                                       if (localContentsOffset + 4 >= this.contents.length) {
+                                               resizeContents(4);
+                                       }
+                                       this.contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
+                                       this.contents[numberOfLocalOffset] = (byte) numberOfEntries;
+                                       int numberOfStackItems = currentFrame.numberOfStackItems;
+                                       this.contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
+                                       this.contents[localContentsOffset++] = (byte) numberOfStackItems;
+                                       for (int i = 0; i < numberOfStackItems; i++) {
+                                               if (localContentsOffset + 3 >= this.contents.length) {
+                                                       resizeContents(3);
+                                               }
+                                               VerificationTypeInfo info = currentFrame.stackItems[i];
+                                               if (info == null) {
+                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
+                                               } else {
+                                                       switch(info.id()) {
+                                                               case T_boolean :
+                                                               case T_byte :
+                                                               case T_char :
+                                                               case T_int :
+                                                               case T_short :
+                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
+                                                                       break;
+                                                               case T_float :
+                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
+                                                                       break;
+                                                               case T_long :
+                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
+                                                                       break;
+                                                               case T_double :
+                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
+                                                                       break;
+                                                               case T_null :
+                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
+                                                                       break;
+                                                               default:
+                                                                       this.contents[localContentsOffset++] = (byte) info.tag;
+                                                               switch (info.tag) {
+                                                                       case VerificationTypeInfo.ITEM_UNINITIALIZED :
+                                                                               int offset = info.offset;
+                                                                               this.contents[localContentsOffset++] = (byte) (offset >> 8);
+                                                                               this.contents[localContentsOffset++] = (byte) offset;
+                                                                               break;
+                                                                       case VerificationTypeInfo.ITEM_OBJECT :
+                                                                               int indexForType = this.constantPool.literalIndexForType(info.constantPoolName());
+                                                                               this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
+                                                                               this.contents[localContentsOffset++] = (byte) indexForType;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               numberOfFrames--;
+                               if (numberOfFrames != 0) {
+                                       this.contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
+                                       this.contents[numberOfFramesOffset] = (byte) numberOfFrames;
+
+                                       int attributeLength = localContentsOffset - stackMapAttributeLengthOffset - 4;
+                                       this.contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 24);
+                                       this.contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 16);
+                                       this.contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 8);
+                                       this.contents[stackMapAttributeLengthOffset] = (byte) attributeLength;
+                                       attributesNumber++;
+                               } else {
+                                       localContentsOffset = stackMapTableAttributeOffset;
+                               }
+                       }
+               }
+               this.contentsOffset = localContentsOffset;
+               return attributesNumber;
+       }
+
+       private int generateStackMapTableAttribute(
+                       MethodBinding methodBinding,
+                       int code_length,
+                       int codeAttributeOffset,
+                       int max_locals,
+                       boolean isClinit) {
+               int attributesNumber = 0;
+               int localContentsOffset = this.contentsOffset;
+               StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream;
+               stackMapFrameCodeStream.removeFramePosition(code_length);
+               if (stackMapFrameCodeStream.hasFramePositions()) {
+                       Map frames = new HashMap();
+                       List realFrames = traverse(isClinit ? null: methodBinding, max_locals, this.contents, codeAttributeOffset + 14, code_length, frames, isClinit);
+                       int numberOfFrames = realFrames.size();
+                       if (numberOfFrames > 1) {
+                               int stackMapTableAttributeOffset = localContentsOffset;
+                               // add the stack map table attribute
+                               if (localContentsOffset + 8 >= this.contents.length) {
+                                       resizeContents(8);
+                               }
+                               int stackMapTableAttributeNameIndex =
+                                       this.constantPool.literalIndex(AttributeNamesConstants.StackMapTableName);
+                               this.contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex;
+
+                               int stackMapTableAttributeLengthOffset = localContentsOffset;
+                               // generate the attribute
+                               localContentsOffset += 4;
+                               if (localContentsOffset + 4 >= this.contents.length) {
+                                       resizeContents(4);
+                               }
+                               int numberOfFramesOffset = localContentsOffset;
+                               localContentsOffset += 2;
+                               if (localContentsOffset + 2 >= this.contents.length) {
+                                       resizeContents(2);
+                               }
+                               StackMapFrame currentFrame = (StackMapFrame) realFrames.get(0);
+                               StackMapFrame prevFrame = null;
+                               for (int j = 1; j < numberOfFrames; j++) {
+                                       // select next frame
+                                       prevFrame = currentFrame;
+                                       currentFrame = (StackMapFrame) realFrames.get(j);
+                                       // generate current frame
+                                       // need to find differences between the current frame and the previous frame
+                                       int offsetDelta = currentFrame.getOffsetDelta(prevFrame);
+                                       switch (currentFrame.getFrameType(prevFrame)) {
+                                               case StackMapFrame.APPEND_FRAME :
+                                                       if (localContentsOffset + 3 >= this.contents.length) {
+                                                               resizeContents(3);
+                                                       }
+                                                       int numberOfDifferentLocals = currentFrame.numberOfDifferentLocals(prevFrame);
+                                                       this.contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals);
+                                                       this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
+                                                       this.contents[localContentsOffset++] = (byte) offsetDelta;
+                                                       int index = currentFrame.getIndexOfDifferentLocals(numberOfDifferentLocals);
+                                                       int numberOfLocals = currentFrame.getNumberOfLocals();
+                                                       for (int i = index; i < currentFrame.locals.length && numberOfDifferentLocals > 0; i++) {
+                                                               if (localContentsOffset + 6 >= this.contents.length) {
+                                                                       resizeContents(6);
+                                                               }
+                                                               VerificationTypeInfo info = currentFrame.locals[i];
+                                                               if (info == null) {
+                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
+                                                               } else {
+                                                                       switch(info.id()) {
+                                                                               case T_boolean :
+                                                                               case T_byte :
+                                                                               case T_char :
+                                                                               case T_int :
+                                                                               case T_short :
+                                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
+                                                                                       break;
+                                                                               case T_float :
+                                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
+                                                                                       break;
+                                                                               case T_long :
+                                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
+                                                                                       i++;
+                                                                                       break;
+                                                                               case T_double :
+                                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
+                                                                                       i++;
+                                                                                       break;
+                                                                               case T_null :
+                                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
+                                                                                       break;
+                                                                               default:
+                                                                                       this.contents[localContentsOffset++] = (byte) info.tag;
+                                                                                       switch (info.tag) {
+                                                                                               case VerificationTypeInfo.ITEM_UNINITIALIZED :
+                                                                                                       int offset = info.offset;
+                                                                                                       this.contents[localContentsOffset++] = (byte) (offset >> 8);
+                                                                                                       this.contents[localContentsOffset++] = (byte) offset;
+                                                                                                       break;
+                                                                                               case VerificationTypeInfo.ITEM_OBJECT :
+                                                                                                       int indexForType = this.constantPool.literalIndexForType(info.constantPoolName());
+                                                                                                       this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
+                                                                                                       this.contents[localContentsOffset++] = (byte) indexForType;
+                                                                                       }
+                                                                       }
+                                                                       numberOfDifferentLocals--;
+                                                               }
+                                                       }
+                                                       break;
+                                               case StackMapFrame.SAME_FRAME :
+                                                       if (localContentsOffset + 1 >= this.contents.length) {
+                                                               resizeContents(1);
+                                                       }
+                                                       this.contents[localContentsOffset++] = (byte) offsetDelta;
+                                                       break;
+                                               case StackMapFrame.SAME_FRAME_EXTENDED :
+                                                       if (localContentsOffset + 3 >= this.contents.length) {
+                                                               resizeContents(3);
+                                                       }
+                                                       this.contents[localContentsOffset++] = (byte) 251;
+                                                       this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
+                                                       this.contents[localContentsOffset++] = (byte) offsetDelta;
+                                                       break;
+                                               case StackMapFrame.CHOP_FRAME :
+                                                       if (localContentsOffset + 3 >= this.contents.length) {
+                                                               resizeContents(3);
+                                                       }
+                                                       numberOfDifferentLocals = -currentFrame.numberOfDifferentLocals(prevFrame);
+                                                       this.contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals);
+                                                       this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
+                                                       this.contents[localContentsOffset++] = (byte) offsetDelta;
+                                                       break;
+                                               case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS :
+                                                       if (localContentsOffset + 4 >= this.contents.length) {
+                                                               resizeContents(4);
+                                                       }
+                                                       this.contents[localContentsOffset++] = (byte) (offsetDelta + 64);
+                                                       if (currentFrame.stackItems[0] == null) {
+                                                               this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
+                                                       } else {
+                                                               switch(currentFrame.stackItems[0].id()) {
+                                                                       case T_boolean :
+                                                                       case T_byte :
+                                                                       case T_char :
+                                                                       case T_int :
+                                                                       case T_short :
+                                                                               this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
+                                                                               break;
+                                                                       case T_float :
+                                                                               this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
+                                                                               break;
+                                                                       case T_long :
+                                                                               this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
+                                                                               break;
+                                                                       case T_double :
+                                                                               this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
+                                                                               break;
+                                                                       case T_null :
+                                                                               this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
+                                                                               break;
+                                                                       default:
+                                                                               VerificationTypeInfo info = currentFrame.stackItems[0];
+                                                                               byte tag = (byte) info.tag;
+                                                                               this.contents[localContentsOffset++] = tag;
+                                                                               switch (tag) {
+                                                                                       case VerificationTypeInfo.ITEM_UNINITIALIZED :
+                                                                                               int offset = info.offset;
+                                                                                               this.contents[localContentsOffset++] = (byte) (offset >> 8);
+                                                                                               this.contents[localContentsOffset++] = (byte) offset;
+                                                                                               break;
+                                                                                       case VerificationTypeInfo.ITEM_OBJECT :
+                                                                                               int indexForType = this.constantPool.literalIndexForType(info.constantPoolName());
+                                                                                               this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
+                                                                                               this.contents[localContentsOffset++] = (byte) indexForType;
+                                                                               }
+                                                               }
+                                                       }
+                                                       break;
+                                               case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED :
+                                                       if (localContentsOffset + 6 >= this.contents.length) {
+                                                               resizeContents(6);
+                                                       }
+                                                       this.contents[localContentsOffset++] = (byte) 247;
+                                                       this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
+                                                       this.contents[localContentsOffset++] = (byte) offsetDelta;
+                                                       if (currentFrame.stackItems[0] == null) {
+                                                               this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
+                                                       } else {
+                                                               switch(currentFrame.stackItems[0].id()) {
+                                                                       case T_boolean :
+                                                                       case T_byte :
+                                                                       case T_char :
+                                                                       case T_int :
+                                                                       case T_short :
+                                                                               this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
+                                                                               break;
+                                                                       case T_float :
+                                                                               this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
+                                                                               break;
+                                                                       case T_long :
+                                                                               this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
+                                                                               break;
+                                                                       case T_double :
+                                                                               this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
+                                                                               break;
+                                                                       case T_null :
+                                                                               this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
+                                                                               break;
+                                                                       default:
+                                                                               VerificationTypeInfo info = currentFrame.stackItems[0];
+                                                                               byte tag = (byte) info.tag;
+                                                                               this.contents[localContentsOffset++] = tag;
+                                                                               switch (tag) {
+                                                                                       case VerificationTypeInfo.ITEM_UNINITIALIZED :
+                                                                                               int offset = info.offset;
+                                                                                               this.contents[localContentsOffset++] = (byte) (offset >> 8);
+                                                                                               this.contents[localContentsOffset++] = (byte) offset;
+                                                                                               break;
+                                                                                       case VerificationTypeInfo.ITEM_OBJECT :
+                                                                                               int indexForType = this.constantPool.literalIndexForType(info.constantPoolName());
+                                                                                               this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
+                                                                                               this.contents[localContentsOffset++] = (byte) indexForType;
+                                                                               }
+                                                               }
+                                                       }
+                                                       break;
+                                               default :
+                                                       // FULL_FRAME
+                                                       if (localContentsOffset + 5 >= this.contents.length) {
+                                                               resizeContents(5);
+                                                       }
+                                                       this.contents[localContentsOffset++] = (byte) 255;
+                                                       this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
+                                                       this.contents[localContentsOffset++] = (byte) offsetDelta;
+                                                       int numberOfLocalOffset = localContentsOffset;
+                                                       localContentsOffset += 2; // leave two spots for number of locals
+                                                       int numberOfLocalEntries = 0;
+                                                       numberOfLocals = currentFrame.getNumberOfLocals();
+                                                       int numberOfEntries = 0;
+                                                       int localsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length;
+                                                       for (int i = 0; i < localsLength && numberOfLocalEntries < numberOfLocals; i++) {
+                                                               if (localContentsOffset + 3 >= this.contents.length) {
+                                                                       resizeContents(3);
+                                                               }
+                                                               VerificationTypeInfo info = currentFrame.locals[i];
+                                                               if (info == null) {
+                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
+                                                               } else {
+                                                                       switch(info.id()) {
+                                                                               case T_boolean :
+                                                                               case T_byte :
+                                                                               case T_char :
+                                                                               case T_int :
+                                                                               case T_short :
+                                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
+                                                                                       break;
+                                                                               case T_float :
+                                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
+                                                                                       break;
+                                                                               case T_long :
+                                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
+                                                                                       i++;
+                                                                                       break;
+                                                                               case T_double :
+                                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
+                                                                                       i++;
+                                                                                       break;
+                                                                               case T_null :
+                                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
+                                                                                       break;
+                                                                               default:
+                                                                                       this.contents[localContentsOffset++] = (byte) info.tag;
+                                                                                       switch (info.tag) {
+                                                                                               case VerificationTypeInfo.ITEM_UNINITIALIZED :
+                                                                                                       int offset = info.offset;
+                                                                                                       this.contents[localContentsOffset++] = (byte) (offset >> 8);
+                                                                                                       this.contents[localContentsOffset++] = (byte) offset;
+                                                                                                       break;
+                                                                                               case VerificationTypeInfo.ITEM_OBJECT :
+                                                                                                       int indexForType = this.constantPool.literalIndexForType(info.constantPoolName());
+                                                                                                       this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
+                                                                                                       this.contents[localContentsOffset++] = (byte) indexForType;
+                                                                                       }
+                                                                       }
+                                                                       numberOfLocalEntries++;
+                                                               }
+                                                               numberOfEntries++;
+                                                       }
+                                                       if (localContentsOffset + 4 >= this.contents.length) {
+                                                               resizeContents(4);
+                                                       }
+                                                       this.contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
+                                                       this.contents[numberOfLocalOffset] = (byte) numberOfEntries;
+                                                       int numberOfStackItems = currentFrame.numberOfStackItems;
+                                                       this.contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
+                                                       this.contents[localContentsOffset++] = (byte) numberOfStackItems;
+                                                       for (int i = 0; i < numberOfStackItems; i++) {
+                                                               if (localContentsOffset + 3 >= this.contents.length) {
+                                                                       resizeContents(3);
+                                                               }
+                                                               VerificationTypeInfo info = currentFrame.stackItems[i];
+                                                               if (info == null) {
+                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
+                                                               } else {
+                                                                       switch(info.id()) {
+                                                                               case T_boolean :
+                                                                               case T_byte :
+                                                                               case T_char :
+                                                                               case T_int :
+                                                                               case T_short :
+                                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
+                                                                                       break;
+                                                                               case T_float :
+                                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
+                                                                                       break;
+                                                                               case T_long :
+                                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
+                                                                                       break;
+                                                                               case T_double :
+                                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
+                                                                                       break;
+                                                                               case T_null :
+                                                                                       this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
+                                                                                       break;
+                                                                               default:
+                                                                                       this.contents[localContentsOffset++] = (byte) info.tag;
+                                                                                       switch (info.tag) {
+                                                                                               case VerificationTypeInfo.ITEM_UNINITIALIZED :
+                                                                                                       int offset = info.offset;
+                                                                                                       this.contents[localContentsOffset++] = (byte) (offset >> 8);
+                                                                                                       this.contents[localContentsOffset++] = (byte) offset;
+                                                                                                       break;
+                                                                                               case VerificationTypeInfo.ITEM_OBJECT :
+                                                                                                       int indexForType = this.constantPool.literalIndexForType(info.constantPoolName());
+                                                                                                       this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
+                                                                                                       this.contents[localContentsOffset++] = (byte) indexForType;
+                                                                                       }
+                                                                       }
+                                                               }
+                                                       }
+                                       }
+                               }
+
+                               numberOfFrames--;
+                               if (numberOfFrames != 0) {
+                                       this.contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
+                                       this.contents[numberOfFramesOffset] = (byte) numberOfFrames;
+
+                                       int attributeLength = localContentsOffset - stackMapTableAttributeLengthOffset - 4;
+                                       this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24);
+                                       this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16);
+                                       this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8);
+                                       this.contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength;
+                                       attributesNumber++;
+                               } else {
+                                       localContentsOffset = stackMapTableAttributeOffset;
+                               }
+                       }
+               }
+               this.contentsOffset = localContentsOffset;
+               return attributesNumber;
+       }
+
+       private int generateSyntheticAttribute() {
+               int localContentsOffset = this.contentsOffset;
+               if (localContentsOffset + 6 >= this.contents.length) {
+                       resizeContents(6);
+               }
+               int syntheticAttributeNameIndex =
+                       this.constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+               this.contents[localContentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+               this.contents[localContentsOffset++] = (byte) syntheticAttributeNameIndex;
+               // the length of a synthetic attribute is equals to 0
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contentsOffset = localContentsOffset;
+               return 1;
+       }
+       
+       private void generateTypeAnnotation(AnnotationContext annotationContext, int currentOffset) {
+               Annotation annotation = annotationContext.annotation.getPersistibleAnnotation();
+               if (annotation == null || annotation.resolvedType == null)
+                       return;
+               
+               int targetType = annotationContext.targetType;
+
+               int[] locations = Annotation.getLocations(
+                       annotationContext.typeReference,
+                       annotationContext.annotation);
+
+               if (this.contentsOffset + 5 >= this.contents.length) {
+                       resizeContents(5);
+               }
+               this.contents[this.contentsOffset++] = (byte) targetType;
+               dumpTargetTypeContents(targetType, annotationContext);
+               dumpLocations(locations);
+               generateAnnotation(annotation, currentOffset);
+       }
+
+       private int generateTypeAnnotationAttributeForTypeDeclaration() {
+               TypeDeclaration typeDeclaration = this.referenceBinding.scope.referenceContext;
+               if ((typeDeclaration.bits & ASTNode.HasTypeAnnotations) == 0) {
+                       return 0;
+               }
+               int attributesNumber = 0;
+               int visibleTypeAnnotationsCounter = 0;
+               int invisibleTypeAnnotationsCounter = 0;
+               TypeReference superclass = typeDeclaration.superclass;
+               List allTypeAnnotationContexts = new ArrayList();
+               if (superclass != null && (superclass.bits & ASTNode.HasTypeAnnotations) != 0) {
+                       superclass.getAllAnnotationContexts(AnnotationTargetTypeConstants.CLASS_EXTENDS, -1, allTypeAnnotationContexts);
+               }
+               TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
+               if (superInterfaces != null) {
+                       for (int i = 0; i < superInterfaces.length; i++) {
+                               TypeReference superInterface = superInterfaces[i];
+                               if ((superInterface.bits & ASTNode.HasTypeAnnotations) == 0) {
+                                       continue;
+                               }
+                               superInterface.getAllAnnotationContexts(AnnotationTargetTypeConstants.CLASS_EXTENDS, i, allTypeAnnotationContexts);
+                       }
+               }
+               TypeParameter[] typeParameters = typeDeclaration.typeParameters;
+               if (typeParameters != null) {
+                       for (int i = 0, max = typeParameters.length; i < max; i++) {
+                               TypeParameter typeParameter = typeParameters[i];
+                               if ((typeParameter.bits & ASTNode.HasTypeAnnotations) != 0) {
+                                       typeParameter.getAllAnnotationContexts(AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER, i, allTypeAnnotationContexts);
+                               }
+                       }
+               }
+               int size = allTypeAnnotationContexts.size();
+               if (size != 0) {
+                       AnnotationContext[] allTypeAnnotationContextsArray = new AnnotationContext[size];
+                       allTypeAnnotationContexts.toArray(allTypeAnnotationContextsArray);
+                       for (int j = 0, max = allTypeAnnotationContextsArray.length; j < max; j++) {
+                               AnnotationContext annotationContext = allTypeAnnotationContextsArray[j];
+                               if ((annotationContext.visibility & AnnotationContext.INVISIBLE) != 0) {
+                                       invisibleTypeAnnotationsCounter++;
+                                       allTypeAnnotationContexts.add(annotationContext);
+                               } else {
+                                       visibleTypeAnnotationsCounter++;
+                                       allTypeAnnotationContexts.add(annotationContext);
+                               }
+                       }
+                       attributesNumber += generateRuntimeTypeAnnotations(
+                                       allTypeAnnotationContextsArray,
+                                       visibleTypeAnnotationsCounter,
+                                       invisibleTypeAnnotationsCounter);
+               }
+               return attributesNumber;
+       }
+       
+       
+       
+
+       private int generateVarargsAttribute() {
+               int localContentsOffset = this.contentsOffset;
+               /*
+                * handle of the target jsr14 for varargs in the source
+                * Varargs attribute
+                * Check that there is enough space to write the attribute
+                */
+               if (localContentsOffset + 6 >= this.contents.length) {
+                       resizeContents(6);
+               }
+               int varargsAttributeNameIndex =
+                       this.constantPool.literalIndex(AttributeNamesConstants.VarargsName);
+               this.contents[localContentsOffset++] = (byte) (varargsAttributeNameIndex >> 8);
+               this.contents[localContentsOffset++] = (byte) varargsAttributeNameIndex;
+               // the length of a varargs attribute is equals to 0
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+
+               this.contentsOffset = localContentsOffset;
+               return 1;
+       }
+
+       /**
+        * EXTERNAL API
+        * Answer the actual bytes of the class file
+        *
+        * This method encodes the receiver structure into a byte array which is the content of the classfile.
+        * Returns the byte array that represents the encoded structure of the receiver.
+        *
+        * @return byte[]
+        */
+       public byte[] getBytes() {
+               if (this.bytes == null) {
+                       this.bytes = new byte[this.headerOffset + this.contentsOffset];
+                       System.arraycopy(this.header, 0, this.bytes, 0, this.headerOffset);
+                       System.arraycopy(this.contents, 0, this.bytes, this.headerOffset, this.contentsOffset);
+               }
+               return this.bytes;
+       }
+       /**
+        * EXTERNAL API
+        * Answer the compound name of the class file.
+        * @return char[][]
+        * e.g. {{java}, {util}, {Hashtable}}.
+        */
+       public char[][] getCompoundName() {
+               return CharOperation.splitOn('/', fileName());
+       }
+
+       private int getParametersCount(char[] methodSignature) {
+               int i = CharOperation.indexOf('(', methodSignature);
+               i++;
+               char currentCharacter = methodSignature[i];
+               if (currentCharacter == ')') {
+                       return 0;
+               }
+               int result = 0;
+               while (true) {
+                       currentCharacter = methodSignature[i];
+                       if (currentCharacter == ')') {
+                               return result;
+                       }
+                       switch (currentCharacter) {
+                               case '[':
+                                       // array type
+                                       int scanType = scanType(methodSignature, i + 1);
+                                       result++;
+                                       i = scanType + 1;
+                                       break;
+                               case 'L':
+                                       scanType = CharOperation.indexOf(';', methodSignature,
+                                                       i + 1);
+                                       result++;
+                                       i = scanType + 1;
+                                       break;
+                               case 'Z':
+                               case 'B':
+                               case 'C':
+                               case 'D':
+                               case 'F':
+                               case 'I':
+                               case 'J':
+                               case 'S':
+                                       result++;
+                                       i++;
+                                       break;
+                               default:
+                                       throw new IllegalArgumentException("Invalid starting type character : " + currentCharacter); //$NON-NLS-1$
+                       }
+               }
+       }
+
+       private char[] getReturnType(char[] methodSignature) {
+               // skip type parameters
+               int paren = CharOperation.lastIndexOf(')', methodSignature);
+               // there could be thrown exceptions behind, thus scan one type exactly
+               return CharOperation.subarray(methodSignature, paren + 1,
+                               methodSignature.length);
+       }
+
+       private final int i4At(byte[] reference, int relativeOffset,
+                       int structOffset) {
+               int position = relativeOffset + structOffset;
+               return ((reference[position++] & 0xFF) << 24)
+                               + ((reference[position++] & 0xFF) << 16)
+                               + ((reference[position++] & 0xFF) << 8)
+                               + (reference[position] & 0xFF);
+       }
+
+       protected void initByteArrays() {
+               int members = this.referenceBinding.methods().length + this.referenceBinding.fields().length;
+               this.header = new byte[INITIAL_HEADER_SIZE];
+               this.contents = new byte[members < 15 ? INITIAL_CONTENTS_SIZE : INITIAL_HEADER_SIZE];
+       }
+
+       public void initialize(SourceTypeBinding aType, ClassFile parentClassFile, boolean createProblemType) {
+               // generate the magic numbers inside the header
+               this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 24);
+               this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 16);
+               this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 8);
+               this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 0);
+
+               long targetVersion = this.targetJDK;
+               this.header[this.headerOffset++] = (byte) (targetVersion >> 8); // minor high
+               this.header[this.headerOffset++] = (byte) (targetVersion>> 0); // minor low
+               this.header[this.headerOffset++] = (byte) (targetVersion >> 24); // major high
+               this.header[this.headerOffset++] = (byte) (targetVersion >> 16); // major low
+
+               this.constantPoolOffset = this.headerOffset;
+               this.headerOffset += 2;
+               this.constantPool.initialize(this);
+
+               // Modifier manipulations for classfile
+               int accessFlags = aType.getAccessFlags();
+               if (aType.isPrivate()) { // rewrite private to non-public
+                       accessFlags &= ~ClassFileConstants.AccPublic;
+               }
+               if (aType.isProtected()) { // rewrite protected into public
+                       accessFlags |= ClassFileConstants.AccPublic;
+               }
+               // clear all bits that are illegal for a class or an interface
+               accessFlags
+                       &= ~(
+                               ClassFileConstants.AccStrictfp
+                                       | ClassFileConstants.AccProtected
+                                       | ClassFileConstants.AccPrivate
+                                       | ClassFileConstants.AccStatic
+                                       | ClassFileConstants.AccSynchronized
+                                       | ClassFileConstants.AccNative);
+
+               // set the AccSuper flag (has to be done after clearing AccSynchronized - since same value)
+               if (!aType.isInterface()) { // class or enum
+                       accessFlags |= ClassFileConstants.AccSuper;
+               }
+               if (aType.isAnonymousType()) {
+                       accessFlags &= ~ClassFileConstants.AccFinal;
+               }
+               int finalAbstract = ClassFileConstants.AccFinal | ClassFileConstants.AccAbstract;
+               if ((accessFlags & finalAbstract) == finalAbstract) {
+                       accessFlags &= ~finalAbstract;
+               }
+               this.enclosingClassFile = parentClassFile;
+               // innerclasses get their names computed at code gen time
+
+               // now we continue to generate the bytes inside the contents array
+               this.contents[this.contentsOffset++] = (byte) (accessFlags >> 8);
+               this.contents[this.contentsOffset++] = (byte) accessFlags;
+               int classNameIndex = this.constantPool.literalIndexForType(aType);
+               this.contents[this.contentsOffset++] = (byte) (classNameIndex >> 8);
+               this.contents[this.contentsOffset++] = (byte) classNameIndex;
+               // AspectJ Extension - don't include result of decp weaving in the class created by compilation
+               /*old{
+               int superclassNameIndex;
+               if (aType.isInterface()) {
+                       superclassNameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName);
+               } else {
+                       if (aType.superclass != null) {
+                                if ((aType.superclass.tagBits & TagBits.HasMissingType) != 0) {
+                                               superclassNameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName);
+                                } else {
+                                               superclassNameIndex = this.constantPool.literalIndexForType(aType.superclass);
+                                }
+                       } else {
+                               superclassNameIndex = 0;
+                       }
+               }
+               }new:*/
+               ReferenceBinding superclass = aType.superclass;
+               int superclassNameIndex;
+               if (aType.originalSuperclass!=null) {
+                       superclass = aType.originalSuperclass;
+               }
+               if (aType.isInterface()) {
+                       superclassNameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName);
+               } else {
+                       if (superclass != null) {
+                                if ((superclass.tagBits & TagBits.HasMissingType) != 0) {
+                                               superclassNameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName);
+                                } else {
+                                               superclassNameIndex = this.constantPool.literalIndexForType(superclass);
+                                }
+                       } else {
+                               superclassNameIndex = 0;
+                       }
+               }               
+               // AspectJ Extension end
+               this.contents[this.contentsOffset++] = (byte) (superclassNameIndex >> 8);
+               this.contents[this.contentsOffset++] = (byte) superclassNameIndex;
+               ReferenceBinding[] superInterfacesBinding = aType.superInterfaces();
+               // AspectJ Extension - don't include result of decp weaving in the class created by compilaton
+               if (aType.originalSuperInterfaces!=null) {
+                       superInterfacesBinding = aType.originalSuperInterfaces;
+               }
+               // AspectJ Extension end
+               int interfacesCount = superInterfacesBinding.length;
+               int interfacesCountPosition = this.contentsOffset;
+               this.contentsOffset += 2;
+               int interfaceCounter = 0;
+               for (int i = 0; i < interfacesCount; i++) {
+                       ReferenceBinding binding = superInterfacesBinding[i];
+                       if ((binding.tagBits & TagBits.HasMissingType) != 0) {
+                               continue;
+                       }
+                       interfaceCounter++;
+                       int interfaceIndex = this.constantPool.literalIndexForType(binding);
+                       this.contents[this.contentsOffset++] = (byte) (interfaceIndex >> 8);
+                       this.contents[this.contentsOffset++] = (byte) interfaceIndex;
+               }
+               this.contents[interfacesCountPosition++] = (byte) (interfaceCounter >> 8);
+               this.contents[interfacesCountPosition] = (byte) interfaceCounter;
+               this.creatingProblemType = createProblemType;
+
+               // retrieve the enclosing one guaranteed to be the one matching the propagated flow info
+               // 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check)
+               this.codeStream.maxFieldCount = aType.scope.outerMostClassScope().referenceType().maxFieldCount;
+       }
+
+       private void initializeDefaultLocals(StackMapFrame frame,
+                       MethodBinding methodBinding,
+                       int maxLocals,
+                       int codeLength) {
+               if (maxLocals != 0) {
+                       int resolvedPosition = 0;
+                       // take into account enum constructor synthetic name+ordinal
+                       final boolean isConstructor = methodBinding.isConstructor();
+                       if (isConstructor || !methodBinding.isStatic()) {
+                               LocalVariableBinding localVariableBinding = new LocalVariableBinding(ConstantPool.This, methodBinding.declaringClass, 0, false);
+                               localVariableBinding.resolvedPosition = 0;
+                               this.codeStream.record(localVariableBinding);
+                               localVariableBinding.recordInitializationStartPC(0);
+                               localVariableBinding.recordInitializationEndPC(codeLength);
+                               frame.putLocal(resolvedPosition, new VerificationTypeInfo(
+                                               isConstructor ? VerificationTypeInfo.ITEM_UNINITIALIZED_THIS : VerificationTypeInfo.ITEM_OBJECT,
+                                               methodBinding.declaringClass));
+                               resolvedPosition++;
+                       }
+
+                       if (isConstructor) {
+                               if (methodBinding.declaringClass.isEnum()) {
+                                       LocalVariableBinding localVariableBinding = new LocalVariableBinding(" name".toCharArray(), this.referenceBinding.scope.getJavaLangString(), 0, false); //$NON-NLS-1$
+                                       localVariableBinding.resolvedPosition = resolvedPosition;
+                                       this.codeStream.record(localVariableBinding);
+                                       localVariableBinding.recordInitializationStartPC(0);
+                                       localVariableBinding.recordInitializationEndPC(codeLength);
+
+                                       frame.putLocal(resolvedPosition, new VerificationTypeInfo(
+                                                       TypeIds.T_JavaLangString,
+                                                       ConstantPool.JavaLangStringConstantPoolName));
+                                       resolvedPosition++;
+
+                                       localVariableBinding = new LocalVariableBinding(" ordinal".toCharArray(), TypeBinding.INT, 0, false); //$NON-NLS-1$
+                                       localVariableBinding.resolvedPosition = resolvedPosition;
+                                       this.codeStream.record(localVariableBinding);
+                                       localVariableBinding.recordInitializationStartPC(0);
+                                       localVariableBinding.recordInitializationEndPC(codeLength);
+                                       frame.putLocal(resolvedPosition, new VerificationTypeInfo(
+                                                       TypeBinding.INT));
+                                       resolvedPosition++;
+                               }
+
+                               // take into account the synthetic parameters
+                               if (methodBinding.declaringClass.isNestedType()) {
+                                       ReferenceBinding enclosingInstanceTypes[];
+                                       if ((enclosingInstanceTypes = methodBinding.declaringClass.syntheticEnclosingInstanceTypes()) != null) {
+                                               for (int i = 0, max = enclosingInstanceTypes.length; i < max; i++) {
+                                                       // an enclosingInstanceType can only be a reference
+                                                       // binding. It cannot be
+                                                       // LongBinding or DoubleBinding
+                                                       LocalVariableBinding localVariableBinding = new LocalVariableBinding((" enclosingType" + i).toCharArray(), enclosingInstanceTypes[i], 0, false); //$NON-NLS-1$
+                                                       localVariableBinding.resolvedPosition = resolvedPosition;
+                                                       this.codeStream.record(localVariableBinding);
+                                                       localVariableBinding.recordInitializationStartPC(0);
+                                                       localVariableBinding.recordInitializationEndPC(codeLength);
+
+                                                       frame.putLocal(resolvedPosition,
+                                                                       new VerificationTypeInfo(enclosingInstanceTypes[i]));
+                                                       resolvedPosition++;
+                                               }
+                                       }
+
+                                       TypeBinding[] arguments;
+                                       if ((arguments = methodBinding.parameters) != null) {
+                                               for (int i = 0, max = arguments.length; i < max; i++) {
+                                                       final TypeBinding typeBinding = arguments[i];
+                                                       frame.putLocal(resolvedPosition,
+                                                                       new VerificationTypeInfo(typeBinding));
+                                                       switch (typeBinding.id) {
+                                                               case TypeIds.T_double:
+                                                               case TypeIds.T_long:
+                                                                       resolvedPosition += 2;
+                                                                       break;
+                                                               default:
+                                                                       resolvedPosition++;
+                                                       }
+                                               }
+                                       }
+
+                                       SyntheticArgumentBinding syntheticArguments[];
+                                       if ((syntheticArguments = methodBinding.declaringClass.syntheticOuterLocalVariables()) != null) {
+                                               for (int i = 0, max = syntheticArguments.length; i < max; i++) {
+                                                       final TypeBinding typeBinding = syntheticArguments[i].type;
+                                                       LocalVariableBinding localVariableBinding = new LocalVariableBinding((" synthetic" + i).toCharArray(), typeBinding, 0, false); //$NON-NLS-1$
+                                                       localVariableBinding.resolvedPosition = resolvedPosition;
+                                                       this.codeStream.record(localVariableBinding);
+                                                       localVariableBinding.recordInitializationStartPC(0);
+                                                       localVariableBinding.recordInitializationEndPC(codeLength);
+
+                                                       frame.putLocal(resolvedPosition,
+                                                                       new VerificationTypeInfo(typeBinding));
+                                                       switch (typeBinding.id) {
+                                                               case TypeIds.T_double:
+                                                               case TypeIds.T_long:
+                                                                       resolvedPosition += 2;
+                                                                       break;
+                                                               default:
+                                                                       resolvedPosition++;
+                                                       }
+                                               }
+                                       }
+                               } else {
+                                       TypeBinding[] arguments;
+                                       if ((arguments = methodBinding.parameters) != null) {
+                                               for (int i = 0, max = arguments.length; i < max; i++) {
+                                                       final TypeBinding typeBinding = arguments[i];
+                                                       frame.putLocal(resolvedPosition,
+                                                                       new VerificationTypeInfo(typeBinding));
+                                                       switch (typeBinding.id) {
+                                                               case TypeIds.T_double:
+                                                               case TypeIds.T_long:
+                                                                       resolvedPosition += 2;
+                                                                       break;
+                                                               default:
+                                                                       resolvedPosition++;
+                                                       }
+                                               }
+                                       }
+                               }
+                       } else {
+                               TypeBinding[] arguments;
+                               if ((arguments = methodBinding.parameters) != null) {
+                                       for (int i = 0, max = arguments.length; i < max; i++) {
+                                               final TypeBinding typeBinding = arguments[i];
+                                               // For the branching complexities in the generated $deserializeLambda$ we need the local variable
+                                               LocalVariableBinding localVariableBinding = new LocalVariableBinding((" synthetic"+i).toCharArray(), typeBinding, 0, true); //$NON-NLS-1$
+                                               localVariableBinding.resolvedPosition = i;
+                                               this.codeStream.record(localVariableBinding);
+                                               localVariableBinding.recordInitializationStartPC(0);
+                                               localVariableBinding.recordInitializationEndPC(codeLength);
+                                               frame.putLocal(resolvedPosition,
+                                                               new VerificationTypeInfo(typeBinding));
+                                               switch (typeBinding.id) {
+                                                       case TypeIds.T_double:
+                                                       case TypeIds.T_long:
+                                                               resolvedPosition += 2;
+                                                               break;
+                                                       default:
+                                                               resolvedPosition++;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       private void initializeLocals(boolean isStatic, int currentPC, StackMapFrame currentFrame) {
+               VerificationTypeInfo[] locals = currentFrame.locals;
+               int localsLength = locals.length;
+               int i = 0;
+               if (!isStatic) {
+                       // we don't want to reset the first local if the method is not static
+                       i = 1;
+               }
+               for (; i < localsLength; i++) {
+                       locals[i] = null;
+               }
+               i = 0;
+               locals: for (int max = this.codeStream.allLocalsCounter; i < max; i++) {
+                       LocalVariableBinding localVariable = this.codeStream.locals[i];
+                       if (localVariable == null) continue;
+                       int resolvedPosition = localVariable.resolvedPosition;
+                       final TypeBinding localVariableTypeBinding = localVariable.type;
+                       inits: for (int j = 0; j < localVariable.initializationCount; j++) {
+                               int startPC = localVariable.initializationPCs[j << 1];
+                               int endPC = localVariable.initializationPCs[(j << 1) + 1];
+                               if (currentPC < startPC) {
+                                       continue inits;
+                               } else if (currentPC < endPC) {
+                                       // the current local is an active local
+                                       if (currentFrame.locals[resolvedPosition] == null) {
+                                               currentFrame.locals[resolvedPosition] =
+                                                               new VerificationTypeInfo(
+                                                                               localVariableTypeBinding);
+                                       }
+                                       continue locals;
+                               }
+                       }
+               }
+       }
+       /**
+        * INTERNAL USE-ONLY
+        * Returns the most enclosing classfile of the receiver. This is used know to store the constant pool name
+        * for all inner types of the receiver.
+        * @return org.aspectj.org.eclipse.jdt.internal.compiler.codegen.ClassFile
+        */
+       public ClassFile outerMostEnclosingClassFile() {
+               ClassFile current = this;
+               while (current.enclosingClassFile != null)
+                       current = current.enclosingClassFile;
+               return current;
+       }
+
+       public void recordInnerClasses(TypeBinding binding) {
+               if (this.innerClassesBindings == null) {
+                       this.innerClassesBindings = new HashSet(INNER_CLASSES_SIZE);
+               }
+               ReferenceBinding innerClass = (ReferenceBinding) binding;
+               this.innerClassesBindings.add(innerClass.erasure().unannotated(false));  // should not emit yet another inner class for Outer.@Inner Inner.
+               ReferenceBinding enclosingType = innerClass.enclosingType();
+               while (enclosingType != null
+                               && enclosingType.isNestedType()) {
+                       this.innerClassesBindings.add(enclosingType.erasure().unannotated(false));
+                       enclosingType = enclosingType.enclosingType();
+               }
+       }
+
+       public int recordBootstrapMethod(FunctionalExpression expression) {
+               if (this.bootstrapMethods == null) {
+                       this.bootstrapMethods = new ArrayList();
+               }
+               this.bootstrapMethods.add(expression);
+               // Record which bootstrap method was assigned to the expression
+               expression.bootstrapMethodNumber = this.bootstrapMethods.size() - 1;
+               return this.bootstrapMethods.size() - 1;
+       }
+
+       public void reset(SourceTypeBinding typeBinding) {
+               // the code stream is reinitialized for each method
+               final CompilerOptions options = typeBinding.scope.compilerOptions();
+               this.referenceBinding = typeBinding;
+               this.isNestedType = typeBinding.isNestedType();
+               this.targetJDK = options.targetJDK;
+               this.produceAttributes = options.produceDebugAttributes;
+               if (this.targetJDK >= ClassFileConstants.JDK1_6) {
+                       this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP_TABLE;
+                       if (this.targetJDK >= ClassFileConstants.JDK1_8) {
+                               this.produceAttributes |= ClassFileConstants.ATTR_TYPE_ANNOTATION;
+                               if (options.produceMethodParameters) {
+                                       this.produceAttributes |= ClassFileConstants.ATTR_METHOD_PARAMETERS;
+                               }
+                       }
+               } else if (this.targetJDK == ClassFileConstants.CLDC_1_1) {
+                       this.targetJDK = ClassFileConstants.JDK1_1; // put back 45.3
+                       this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP;
+               }
+               this.bytes = null;
+               this.constantPool.reset();
+               this.codeStream.reset(this);
+               this.constantPoolOffset = 0;
+               this.contentsOffset = 0;
+               this.creatingProblemType = false;
+               this.enclosingClassFile = null;
+               this.headerOffset = 0;
+               this.methodCount = 0;
+               this.methodCountOffset = 0;
+               if (this.innerClassesBindings != null) {
+                       this.innerClassesBindings.clear();
+               }
+               if (this.bootstrapMethods != null) {
+                       this.bootstrapMethods.clear();
+               }
+               this.missingTypes = null;
+               this.visitedTypes = null;
+       }
+
+       /**
+        * Resize the pool contents
+        */
+       private final void resizeContents(int minimalSize) {
+               int length = this.contents.length;
+               int toAdd = length;
+               if (toAdd < minimalSize)
+                       toAdd = minimalSize;
+               System.arraycopy(this.contents, 0, this.contents = new byte[length + toAdd], 0, length);
+       }
+
+       private VerificationTypeInfo retrieveLocal(int currentPC, int resolvedPosition) {
+               for (int i = 0, max = this.codeStream.allLocalsCounter; i < max; i++) {
+                       LocalVariableBinding localVariable = this.codeStream.locals[i];
+                       if (localVariable == null) continue;
+                       if (resolvedPosition == localVariable.resolvedPosition) {
+                               inits: for (int j = 0; j < localVariable.initializationCount; j++) {
+                                       int startPC = localVariable.initializationPCs[j << 1];
+                                       int endPC = localVariable.initializationPCs[(j << 1) + 1];
+                                       if (currentPC < startPC) {
+                                               continue inits;
+                                       } else if (currentPC < endPC) {
+                                               // the current local is an active local
+                                               return new VerificationTypeInfo(localVariable.type);
+                                       }
+                               }
+                       }
+               }
+               return null;
+       }
+
+       private int scanType(char[] methodSignature, int index) {
+               switch (methodSignature[index]) {
+                       case '[':
+                               // array type
+                               return scanType(methodSignature, index + 1);
+                       case 'L':
+                               return CharOperation.indexOf(';', methodSignature, index + 1);
+                       case 'Z':
+                       case 'B':
+                       case 'C':
+                       case 'D':
+                       case 'F':
+                       case 'I':
+                       case 'J':
+                       case 'S':
+                               return index;
+                       default:
+                               throw new IllegalArgumentException();
+               }
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This methods leaves the space for method counts recording.
+        */
+       public void setForMethodInfos() {
+               // leave some space for the methodCount
+               this.methodCountOffset = this.contentsOffset;
+               this.contentsOffset += 2;
+       }
+       
+       private List filterFakeFrames(Set realJumpTargets, Map frames, int codeLength) {
+               // no more frame to generate
+               // filter out "fake" frames
+               realJumpTargets.remove(new Integer(codeLength));
+               List result = new ArrayList();
+               for (Iterator iterator = realJumpTargets.iterator(); iterator.hasNext(); ) {
+                       Integer jumpTarget = (Integer) iterator.next();
+                       StackMapFrame frame = (StackMapFrame) frames.get(jumpTarget);
+                       if (frame != null) {
+                               result.add(frame);
+                       }
+               }
+               Collections.sort(result, new Comparator() {
+                       public int compare(Object o1, Object o2) {
+                               StackMapFrame frame = (StackMapFrame) o1;
+                               StackMapFrame frame2 = (StackMapFrame) o2;
+                               return frame.pc - frame2.pc;
+                       }
+               });
+               return result;
+       }
+
+       public List traverse(MethodBinding methodBinding, int maxLocals, byte[] bytecodes, int codeOffset, int codeLength, Map frames, boolean isClinit) {
+               Set realJumpTarget = new HashSet(); 
+
+               StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream;
+               int[] framePositions = stackMapFrameCodeStream.getFramePositions();
+               int pc = codeOffset;
+               int index;
+               int[] constantPoolOffsets = this.constantPool.offsets;
+               byte[] poolContents = this.constantPool.poolContent;
+
+               // set initial values for frame positions
+               int indexInFramePositions = 0;
+               int framePositionsLength = framePositions.length;
+               int currentFramePosition = framePositions[0];
+
+               // set initial values for stack depth markers
+               int indexInStackDepthMarkers = 0;
+               StackDepthMarker[] stackDepthMarkers = stackMapFrameCodeStream.getStackDepthMarkers();
+               int stackDepthMarkersLength = stackDepthMarkers == null ? 0 : stackDepthMarkers.length;
+               boolean hasStackDepthMarkers = stackDepthMarkersLength != 0;
+               StackDepthMarker stackDepthMarker = null;
+               if (hasStackDepthMarkers) {
+                       stackDepthMarker = stackDepthMarkers[0];
+               }
+
+               // set initial values for stack markers (used only in cldc mode)
+               int indexInStackMarkers = 0;
+               StackMarker[] stackMarkers = stackMapFrameCodeStream.getStackMarkers();
+               int stackMarkersLength = stackMarkers == null ? 0 : stackMarkers.length;
+               boolean hasStackMarkers = stackMarkersLength != 0;
+               StackMarker stackMarker = null;
+               if (hasStackMarkers) {
+                       stackMarker = stackMarkers[0];
+               }
+
+               // set initial values for exception markers
+               int indexInExceptionMarkers = 0;
+               ExceptionMarker[] exceptionMarkers= stackMapFrameCodeStream.getExceptionMarkers();
+               int exceptionsMarkersLength = exceptionMarkers == null ? 0 : exceptionMarkers.length;
+               boolean hasExceptionMarkers = exceptionsMarkersLength != 0;
+               ExceptionMarker exceptionMarker = null;
+               if (hasExceptionMarkers) {
+                       exceptionMarker = exceptionMarkers[0];
+               }
+
+               StackMapFrame frame = new StackMapFrame(maxLocals);
+               if (!isClinit) {
+                       initializeDefaultLocals(frame, methodBinding, maxLocals, codeLength);
+               }
+               frame.pc = -1;
+               add(frames, frame.duplicate());
+               addRealJumpTarget(realJumpTarget, -1);
+               for (int i = 0, max = this.codeStream.exceptionLabelsCounter; i < max; i++) {
+                       ExceptionLabel exceptionLabel = this.codeStream.exceptionLabels[i];
+                       if (exceptionLabel != null) {
+                               addRealJumpTarget(realJumpTarget, exceptionLabel.position);
+                       }
+               }
+               while (true) {
+                       int currentPC = pc - codeOffset;
+                       if (hasStackMarkers && stackMarker.pc == currentPC) {
+                               VerificationTypeInfo[] infos = frame.stackItems;
+                               VerificationTypeInfo[] tempInfos = new VerificationTypeInfo[frame.numberOfStackItems];
+                               System.arraycopy(infos, 0, tempInfos, 0, frame.numberOfStackItems);
+                               stackMarker.setInfos(tempInfos);
+                       } else if (hasStackMarkers && stackMarker.destinationPC == currentPC) {
+                               VerificationTypeInfo[] infos = stackMarker.infos;
+                               frame.stackItems = infos;
+                               frame.numberOfStackItems = infos.length;
+                               indexInStackMarkers++;
+                               if (indexInStackMarkers < stackMarkersLength) {
+                                       stackMarker = stackMarkers[indexInStackMarkers];
+                               } else {
+                                       hasStackMarkers = false;
+                               }
+                       }
+                       if (hasStackDepthMarkers && stackDepthMarker.pc == currentPC) {
+                               TypeBinding typeBinding = stackDepthMarker.typeBinding;
+                               if (typeBinding != null) {
+                                       if (stackDepthMarker.delta > 0) {
+                                               frame.addStackItem(new VerificationTypeInfo(typeBinding));
+                                       } else {
+                                               frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(typeBinding);
+                                       }
+                               } else {
+                                       frame.numberOfStackItems--;
+                               }
+                               indexInStackDepthMarkers++;
+                               if (indexInStackDepthMarkers < stackDepthMarkersLength) {
+                                       stackDepthMarker = stackDepthMarkers[indexInStackDepthMarkers];
+                               } else {
+                                       hasStackDepthMarkers = false;
+                               }
+                       }
+                       if (hasExceptionMarkers && exceptionMarker.pc == currentPC) {
+                               frame.numberOfStackItems = 0;
+                               frame.addStackItem(new VerificationTypeInfo(0, VerificationTypeInfo.ITEM_OBJECT, exceptionMarker.constantPoolName));
+                               indexInExceptionMarkers++;
+                               if (indexInExceptionMarkers < exceptionsMarkersLength) {
+                                       exceptionMarker = exceptionMarkers[indexInExceptionMarkers];
+                               } else {
+                                       hasExceptionMarkers = false;
+                               }
+                       }
+                       if (currentFramePosition < currentPC) {
+                               do {
+                                       indexInFramePositions++;
+                                       if (indexInFramePositions < framePositionsLength) {
+                                               currentFramePosition = framePositions[indexInFramePositions];
+                                       } else {
+                                               currentFramePosition = Integer.MAX_VALUE;
+                                       }
+                               } while (currentFramePosition < currentPC);
+                       }
+                       if (currentFramePosition == currentPC) {
+                               // need to build a new frame and create a stack map attribute entry
+                               StackMapFrame currentFrame = frame.duplicate();
+                               currentFrame.pc = currentPC;
+                               // initialize locals
+                               initializeLocals(isClinit ? true : methodBinding.isStatic(), currentPC, currentFrame);
+                               // insert a new frame
+                               add(frames, currentFrame);
+                               indexInFramePositions++;
+                               if (indexInFramePositions < framePositionsLength) {
+                                       currentFramePosition = framePositions[indexInFramePositions];
+                               } else {
+                                       currentFramePosition = Integer.MAX_VALUE;
+                               }
+                       }
+                       byte opcode = (byte) u1At(bytecodes, 0, pc);
+                       switch (opcode) {
+                               case Opcodes.OPC_nop:
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_aconst_null:
+                                       frame.addStackItem(TypeBinding.NULL);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_iconst_m1:
+                               case Opcodes.OPC_iconst_0:
+                               case Opcodes.OPC_iconst_1:
+                               case Opcodes.OPC_iconst_2:
+                               case Opcodes.OPC_iconst_3:
+                               case Opcodes.OPC_iconst_4:
+                               case Opcodes.OPC_iconst_5:
+                                       frame.addStackItem(TypeBinding.INT);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_lconst_0:
+                               case Opcodes.OPC_lconst_1:
+                                       frame.addStackItem(TypeBinding.LONG);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_fconst_0:
+                               case Opcodes.OPC_fconst_1:
+                               case Opcodes.OPC_fconst_2:
+                                       frame.addStackItem(TypeBinding.FLOAT);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_dconst_0:
+                               case Opcodes.OPC_dconst_1:
+                                       frame.addStackItem(TypeBinding.DOUBLE);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_bipush:
+                                       frame.addStackItem(TypeBinding.BYTE);
+                                       pc += 2;
+                                       break;
+                               case Opcodes.OPC_sipush:
+                                       frame.addStackItem(TypeBinding.SHORT);
+                                       pc += 3;
+                                       break;
+                               case Opcodes.OPC_ldc:
+                                       index = u1At(bytecodes, 1, pc);
+                                       switch (u1At(poolContents, 0, constantPoolOffsets[index])) {
+                                               case ClassFileConstants.StringTag:
+                                                       frame
+                                                                       .addStackItem(new VerificationTypeInfo(
+                                                                                       TypeIds.T_JavaLangString,
+                                                                                       ConstantPool.JavaLangStringConstantPoolName));
+                                                       break;
+                                               case ClassFileConstants.IntegerTag:
+                                                       frame.addStackItem(TypeBinding.INT);
+                                                       break;
+                                               case ClassFileConstants.FloatTag:
+                                                       frame.addStackItem(TypeBinding.FLOAT);
+                                                       break;
+                                               case ClassFileConstants.ClassTag:
+                                                       frame.addStackItem(new VerificationTypeInfo(
+                                                                       TypeIds.T_JavaLangClass,
+                                                                       ConstantPool.JavaLangClassConstantPoolName));
+                                       }
+                                       pc += 2;
+                                       break;
+                               case Opcodes.OPC_ldc_w:
+                                       index = u2At(bytecodes, 1, pc);
+                                       switch (u1At(poolContents, 0, constantPoolOffsets[index])) {
+                                               case ClassFileConstants.StringTag:
+                                                       frame
+                                                                       .addStackItem(new VerificationTypeInfo(
+                                                                                       TypeIds.T_JavaLangString,
+                                                                                       ConstantPool.JavaLangStringConstantPoolName));
+                                                       break;
+                                               case ClassFileConstants.IntegerTag:
+                                                       frame.addStackItem(TypeBinding.INT);
+                                                       break;
+                                               case ClassFileConstants.FloatTag:
+                                                       frame.addStackItem(TypeBinding.FLOAT);
+                                                       break;
+                                               case ClassFileConstants.ClassTag:
+                                                       frame.addStackItem(new VerificationTypeInfo(
+                                                                       TypeIds.T_JavaLangClass,
+                                                                       ConstantPool.JavaLangClassConstantPoolName));
+                                       }
+                                       pc += 3;
+                                       break;
+                               case Opcodes.OPC_ldc2_w:
+                                       index = u2At(bytecodes, 1, pc);
+                                       switch (u1At(poolContents, 0, constantPoolOffsets[index])) {
+                                               case ClassFileConstants.DoubleTag:
+                                                       frame.addStackItem(TypeBinding.DOUBLE);
+                                                       break;
+                                               case ClassFileConstants.LongTag:
+                                                       frame.addStackItem(TypeBinding.LONG);
+                                                       break;
+                                       }
+                                       pc += 3;
+                                       break;
+                               case Opcodes.OPC_iload:
+                                       frame.addStackItem(TypeBinding.INT);
+                                       pc += 2;
+                                       break;
+                               case Opcodes.OPC_lload:
+                                       frame.addStackItem(TypeBinding.LONG);
+                                       pc += 2;
+                                       break;
+                               case Opcodes.OPC_fload:
+                                       frame.addStackItem(TypeBinding.FLOAT);
+                                       pc += 2;
+                                       break;
+                               case Opcodes.OPC_dload:
+                                       frame.addStackItem(TypeBinding.DOUBLE);
+                                       pc += 2;
+                                       break;
+                               case Opcodes.OPC_aload:
+                                       index = u1At(bytecodes, 1, pc);
+                                       VerificationTypeInfo localsN = retrieveLocal(currentPC, index);
+                                       frame.addStackItem(localsN);
+                                       pc += 2;
+                                       break;
+                               case Opcodes.OPC_iload_0:
+                               case Opcodes.OPC_iload_1:
+                               case Opcodes.OPC_iload_2:
+                               case Opcodes.OPC_iload_3:
+                                       frame.addStackItem(TypeBinding.INT);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_lload_0:
+                               case Opcodes.OPC_lload_1:
+                               case Opcodes.OPC_lload_2:
+                               case Opcodes.OPC_lload_3:
+                                       frame.addStackItem(TypeBinding.LONG);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_fload_0:
+                               case Opcodes.OPC_fload_1:
+                               case Opcodes.OPC_fload_2:
+                               case Opcodes.OPC_fload_3:
+                                       frame.addStackItem(TypeBinding.FLOAT);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_dload_0:
+                               case Opcodes.OPC_dload_1:
+                               case Opcodes.OPC_dload_2:
+                               case Opcodes.OPC_dload_3:
+                                       frame.addStackItem(TypeBinding.DOUBLE);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_aload_0:
+                                       VerificationTypeInfo locals0 = frame.locals[0];
+                                       if (locals0 == null || locals0.tag != VerificationTypeInfo.ITEM_UNINITIALIZED_THIS) {
+                                               // special case to handle uninitialized object
+                                               locals0 = retrieveLocal(currentPC, 0);
+                                       }
+                                       frame.addStackItem(locals0);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_aload_1:
+                                       VerificationTypeInfo locals1 = retrieveLocal(currentPC, 1);
+                                       frame.addStackItem(locals1);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_aload_2:
+                                       VerificationTypeInfo locals2 = retrieveLocal(currentPC, 2);
+                                       frame.addStackItem(locals2);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_aload_3:
+                                       VerificationTypeInfo locals3 = retrieveLocal(currentPC, 3);
+                                       frame.addStackItem(locals3);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_iaload:
+                                       frame.numberOfStackItems -=2;
+                                       frame.addStackItem(TypeBinding.INT);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_laload:
+                                       frame.numberOfStackItems -=2;
+                                       frame.addStackItem(TypeBinding.LONG);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_faload:
+                                       frame.numberOfStackItems -=2;
+                                       frame.addStackItem(TypeBinding.FLOAT);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_daload:
+                                       frame.numberOfStackItems -=2;
+                                       frame.addStackItem(TypeBinding.DOUBLE);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_aaload:
+                                       frame.numberOfStackItems--;
+                                       frame.replaceWithElementType();
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_baload:
+                                       frame.numberOfStackItems -=2;
+                                       frame.addStackItem(TypeBinding.BYTE);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_caload:
+                                       frame.numberOfStackItems -=2;
+                                       frame.addStackItem(TypeBinding.CHAR);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_saload:
+                                       frame.numberOfStackItems -=2;
+                                       frame.addStackItem(TypeBinding.SHORT);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_istore:
+                               case Opcodes.OPC_lstore:
+                               case Opcodes.OPC_fstore:
+                               case Opcodes.OPC_dstore:
+                                       frame.numberOfStackItems--;
+                                       pc += 2;
+                                       break;
+                               case Opcodes.OPC_astore:
+                                       index = u1At(bytecodes, 1, pc);
+                                       frame.numberOfStackItems--;
+                                       pc += 2;
+                                       break;
+                               case Opcodes.OPC_astore_0:
+                                       frame.locals[0] = frame.stackItems[frame.numberOfStackItems - 1];
+                                       frame.numberOfStackItems--;
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_astore_1:
+                               case Opcodes.OPC_astore_2:
+                               case Opcodes.OPC_astore_3:
+                               case Opcodes.OPC_istore_0:
+                               case Opcodes.OPC_istore_1:
+                               case Opcodes.OPC_istore_2:
+                               case Opcodes.OPC_istore_3:
+                               case Opcodes.OPC_lstore_0:
+                               case Opcodes.OPC_lstore_1:
+                               case Opcodes.OPC_lstore_2:
+                               case Opcodes.OPC_lstore_3:
+                               case Opcodes.OPC_fstore_0:
+                               case Opcodes.OPC_fstore_1:
+                               case Opcodes.OPC_fstore_2:
+                               case Opcodes.OPC_fstore_3:
+                               case Opcodes.OPC_dstore_0:
+                               case Opcodes.OPC_dstore_1:
+                               case Opcodes.OPC_dstore_2:
+                               case Opcodes.OPC_dstore_3:
+                                       frame.numberOfStackItems--;
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_iastore:
+                               case Opcodes.OPC_lastore:
+                               case Opcodes.OPC_fastore:
+                               case Opcodes.OPC_dastore:
+                               case Opcodes.OPC_aastore:
+                               case Opcodes.OPC_bastore:
+                               case Opcodes.OPC_castore:
+                               case Opcodes.OPC_sastore:
+                                       frame.numberOfStackItems-=3;
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_pop:
+                                       frame.numberOfStackItems--;
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_pop2:
+                                       int numberOfStackItems = frame.numberOfStackItems;
+                                       switch(frame.stackItems[numberOfStackItems - 1].id()) {
+                                               case TypeIds.T_long :
+                                               case TypeIds.T_double :
+                                                       frame.numberOfStackItems--;
+                                                       break;
+                                               default:
+                                                       frame.numberOfStackItems -= 2;
+                                       }
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_dup:
+                                       frame.addStackItem(frame.stackItems[frame.numberOfStackItems - 1]);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_dup_x1:
+                                       VerificationTypeInfo info = frame.stackItems[frame.numberOfStackItems - 1];
+                                       frame.numberOfStackItems--;
+                                       VerificationTypeInfo info2 = frame.stackItems[frame.numberOfStackItems - 1];
+                                       frame.numberOfStackItems--;
+                                       frame.addStackItem(info);
+                                       frame.addStackItem(info2);
+                                       frame.addStackItem(info);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_dup_x2:
+                                       info = frame.stackItems[frame.numberOfStackItems - 1];
+                                       frame.numberOfStackItems--;
+                                       info2 = frame.stackItems[frame.numberOfStackItems - 1];
+                                       frame.numberOfStackItems--;
+                                       switch(info2.id()) {
+                                               case TypeIds.T_long :
+                                               case TypeIds.T_double :
+                                                       frame.addStackItem(info);
+                                                       frame.addStackItem(info2);
+                                                       frame.addStackItem(info);
+                                                       break;
+                                               default:
+                                                       numberOfStackItems = frame.numberOfStackItems;
+                                                       VerificationTypeInfo info3 = frame.stackItems[numberOfStackItems - 1];
+                                                       frame.numberOfStackItems--;
+                                                       frame.addStackItem(info);
+                                                       frame.addStackItem(info3);
+                                                       frame.addStackItem(info2);
+                                                       frame.addStackItem(info);
+                                       }
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_dup2:
+                                       info = frame.stackItems[frame.numberOfStackItems - 1];
+                                       frame.numberOfStackItems--;
+                                       switch(info.id()) {
+                                               case TypeIds.T_double :
+                                               case TypeIds.T_long :
+                                                       frame.addStackItem(info);
+                                                       frame.addStackItem(info);
+                                                       break;
+                                               default:
+                                                       info2 = frame.stackItems[frame.numberOfStackItems - 1];
+                                                       frame.numberOfStackItems--;
+                                                       frame.addStackItem(info2);
+                                                       frame.addStackItem(info);
+                                                       frame.addStackItem(info2);
+                                                       frame.addStackItem(info);
+                                       }
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_dup2_x1:
+                                       info = frame.stackItems[frame.numberOfStackItems - 1];
+                                       frame.numberOfStackItems--;
+                                       info2 = frame.stackItems[frame.numberOfStackItems - 1];
+                                       frame.numberOfStackItems--;
+                                       switch(info.id()) {
+                                               case TypeIds.T_double :
+                                               case TypeIds.T_long :
+                                                       frame.addStackItem(info);
+                                                       frame.addStackItem(info2);
+                                                       frame.addStackItem(info);
+                                                       break;
+                                               default:
+                                                       VerificationTypeInfo info3 = frame.stackItems[frame.numberOfStackItems - 1];
+                                                       frame.numberOfStackItems--;
+                                                       frame.addStackItem(info2);
+                                                       frame.addStackItem(info);
+                                                       frame.addStackItem(info3);
+                                                       frame.addStackItem(info2);
+                                                       frame.addStackItem(info);
+                                       }
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_dup2_x2:
+                                       numberOfStackItems = frame.numberOfStackItems;
+                                       info = frame.stackItems[numberOfStackItems - 1];
+                                       frame.numberOfStackItems--;
+                                       info2 = frame.stackItems[frame.numberOfStackItems - 1];
+                                       frame.numberOfStackItems--;
+                                       switch(info.id()) {
+                                               case TypeIds.T_long :
+                                               case TypeIds.T_double :
+                                                       switch(info2.id()) {
+                                                               case TypeIds.T_long :
+                                                               case TypeIds.T_double :
+                                                                       // form 4
+                                                                       frame.addStackItem(info);
+                                                                       frame.addStackItem(info2);
+                                                                       frame.addStackItem(info);
+                                                                       break;
+                                                               default:
+                                                                       // form 2
+                                                                       numberOfStackItems = frame.numberOfStackItems;
+                                                                       VerificationTypeInfo info3 = frame.stackItems[numberOfStackItems - 1];
+                                                                       frame.numberOfStackItems--;
+                                                                       frame.addStackItem(info);
+                                                                       frame.addStackItem(info3);
+                                                                       frame.addStackItem(info2);
+                                                                       frame.addStackItem(info);
+                                                       }
+                                                       break;
+                                               default:
+                                                       numberOfStackItems = frame.numberOfStackItems;
+                                                       VerificationTypeInfo info3 = frame.stackItems[numberOfStackItems - 1];
+                                                       frame.numberOfStackItems--;
+                                                       switch(info3.id()) {
+                                                               case TypeIds.T_long :
+                                                               case TypeIds.T_double :
+                                                                       // form 3
+                                                                       frame.addStackItem(info2);
+                                                                       frame.addStackItem(info);
+                                                                       frame.addStackItem(info3);
+                                                                       frame.addStackItem(info2);
+                                                                       frame.addStackItem(info);
+                                                                       break;
+                                                               default:
+                                                                       // form 1
+                                                                       numberOfStackItems = frame.numberOfStackItems;
+                                                                       VerificationTypeInfo info4 = frame.stackItems[numberOfStackItems - 1];
+                                                                       frame.numberOfStackItems--;
+                                                                       frame.addStackItem(info2);
+                                                                       frame.addStackItem(info);
+                                                                       frame.addStackItem(info4);
+                                                                       frame.addStackItem(info3);
+                                                                       frame.addStackItem(info2);
+                                                                       frame.addStackItem(info);
+                                                       }
+                                       }
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_swap:
+                                       numberOfStackItems = frame.numberOfStackItems;
+                                       info = frame.stackItems[numberOfStackItems - 1];
+                                       info2 = frame.stackItems[numberOfStackItems - 2];
+                                       frame.stackItems[numberOfStackItems - 1] = info2;
+                                       frame.stackItems[numberOfStackItems - 2] = info;
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_iadd:
+                               case Opcodes.OPC_ladd:
+                               case Opcodes.OPC_fadd:
+                               case Opcodes.OPC_dadd:
+                               case Opcodes.OPC_isub:
+                               case Opcodes.OPC_lsub:
+                               case Opcodes.OPC_fsub:
+                               case Opcodes.OPC_dsub:
+                               case Opcodes.OPC_imul:
+                               case Opcodes.OPC_lmul:
+                               case Opcodes.OPC_fmul:
+                               case Opcodes.OPC_dmul:
+                               case Opcodes.OPC_idiv:
+                               case Opcodes.OPC_ldiv:
+                               case Opcodes.OPC_fdiv:
+                               case Opcodes.OPC_ddiv:
+                               case Opcodes.OPC_irem:
+                               case Opcodes.OPC_lrem:
+                               case Opcodes.OPC_frem:
+                               case Opcodes.OPC_drem:
+                               case Opcodes.OPC_ishl:
+                               case Opcodes.OPC_lshl:
+                               case Opcodes.OPC_ishr:
+                               case Opcodes.OPC_lshr:
+                               case Opcodes.OPC_iushr:
+                               case Opcodes.OPC_lushr:
+                               case Opcodes.OPC_iand:
+                               case Opcodes.OPC_land:
+                               case Opcodes.OPC_ior:
+                               case Opcodes.OPC_lor:
+                               case Opcodes.OPC_ixor:
+                               case Opcodes.OPC_lxor:
+                                       frame.numberOfStackItems--;
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_ineg:
+                               case Opcodes.OPC_lneg:
+                               case Opcodes.OPC_fneg:
+                               case Opcodes.OPC_dneg:
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_iinc:
+                                       pc += 3;
+                                       break;
+                               case Opcodes.OPC_i2l:
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.LONG);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_i2f:
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.FLOAT);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_i2d:
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.DOUBLE);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_l2i:
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.INT);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_l2f:
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.FLOAT);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_l2d:
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.DOUBLE);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_f2i:
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.INT);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_f2l:
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.LONG);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_f2d:
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.DOUBLE);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_d2i:
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.INT);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_d2l:
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.LONG);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_d2f:
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.FLOAT);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_i2b:
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.BYTE);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_i2c:
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.CHAR);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_i2s:
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.SHORT);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_lcmp:
+                               case Opcodes.OPC_fcmpl:
+                               case Opcodes.OPC_fcmpg:
+                               case Opcodes.OPC_dcmpl:
+                               case Opcodes.OPC_dcmpg:
+                                       frame.numberOfStackItems-=2;
+                                       frame.addStackItem(TypeBinding.INT);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_ifeq:
+                               case Opcodes.OPC_ifne:
+                               case Opcodes.OPC_iflt:
+                               case Opcodes.OPC_ifge:
+                               case Opcodes.OPC_ifgt:
+                               case Opcodes.OPC_ifle:
+                                       frame.numberOfStackItems--;
+                                       addRealJumpTarget(realJumpTarget, currentPC + i2At(bytecodes, 1, pc));
+                                       pc += 3;
+                                       break;
+                               case Opcodes.OPC_if_icmpeq:
+                               case Opcodes.OPC_if_icmpne:
+                               case Opcodes.OPC_if_icmplt:
+                               case Opcodes.OPC_if_icmpge:
+                               case Opcodes.OPC_if_icmpgt:
+                               case Opcodes.OPC_if_icmple:
+                               case Opcodes.OPC_if_acmpeq:
+                               case Opcodes.OPC_if_acmpne:
+                                       frame.numberOfStackItems -= 2;
+                                       addRealJumpTarget(realJumpTarget, currentPC + i2At(bytecodes, 1, pc));
+                                       pc += 3;
+                                       break;
+                               case Opcodes.OPC_goto:
+                                       addRealJumpTarget(realJumpTarget, currentPC + i2At(bytecodes, 1, pc));
+                                       pc += 3;
+                                       addRealJumpTarget(realJumpTarget, pc - codeOffset);
+                                       break;
+                               case Opcodes.OPC_tableswitch:
+                                       pc++;
+                                       while (((pc - codeOffset) & 0x03) != 0) {
+                                               pc++;
+                                       }
+                                       // default offset
+                                       addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 0, pc));
+                                       pc += 4; // default
+                                       int low = i4At(bytecodes, 0, pc);
+                                       pc += 4;
+                                       int high = i4At(bytecodes, 0, pc);
+                                       pc += 4;
+                                       int length = high - low + 1;
+                                       for (int i = 0; i < length; i++) {
+                                               // pair offset
+                                               addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 0, pc));
+                                               pc += 4;
+                                       }
+                                       frame.numberOfStackItems--;
+                                       break;
+                               case Opcodes.OPC_lookupswitch:
+                                       pc++;
+                                       while (((pc - codeOffset) & 0x03) != 0) {
+                                               pc++;
+                                       }
+                                       addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 0, pc));
+                                       pc += 4; // default offset
+                                       int npairs = (int) u4At(bytecodes, 0, pc);
+                                       pc += 4; // npair value
+                                       for (int i = 0; i < npairs; i++) {
+                                               pc += 4; // case value
+                                               // pair offset
+                                               addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 0, pc));
+                                               pc += 4;
+                                       }
+                                       frame.numberOfStackItems--;
+                                       break;
+                               case Opcodes.OPC_ireturn:
+                               case Opcodes.OPC_lreturn:
+                               case Opcodes.OPC_freturn:
+                               case Opcodes.OPC_dreturn:
+                               case Opcodes.OPC_areturn:
+                                       frame.numberOfStackItems--;
+                                       pc++;
+                                       addRealJumpTarget(realJumpTarget, pc - codeOffset);
+                                       break;
+                               case Opcodes.OPC_return:
+                                       pc++;
+                                       addRealJumpTarget(realJumpTarget, pc - codeOffset);
+                                       break;
+                               case Opcodes.OPC_getstatic:
+                                       index = u2At(bytecodes, 1, pc);
+                                       int nameAndTypeIndex = u2At(poolContents, 3,
+                                                       constantPoolOffsets[index]);
+                                       int utf8index = u2At(poolContents, 3,
+                                                       constantPoolOffsets[nameAndTypeIndex]);
+                                       char[] descriptor = utf8At(poolContents,
+                                                       constantPoolOffsets[utf8index] + 3, u2At(
+                                                                       poolContents, 1,
+                                                                       constantPoolOffsets[utf8index]));
+                                       if (descriptor.length == 1) {
+                                               // base type
+                                               switch(descriptor[0]) {
+                                                       case 'Z':
+                                                               frame.addStackItem(TypeBinding.BOOLEAN);
+                                                               break;
+                                                       case 'B':
+                                                               frame.addStackItem(TypeBinding.BYTE);
+                                                               break;
+                                                       case 'C':
+                                                               frame.addStackItem(TypeBinding.CHAR);
+                                                               break;
+                                                       case 'D':
+                                                               frame.addStackItem(TypeBinding.DOUBLE);
+                                                               break;
+                                                       case 'F':
+                                                               frame.addStackItem(TypeBinding.FLOAT);
+                                                               break;
+                                                       case 'I':
+                                                               frame.addStackItem(TypeBinding.INT);
+                                                               break;
+                                                       case 'J':
+                                                               frame.addStackItem(TypeBinding.LONG);
+                                                               break;
+                                                       case 'S':
+                                                               frame.addStackItem(TypeBinding.SHORT);
+                                                               break;
+                                               }
+                                       } else if (descriptor[0] == '[') {
+                                               frame.addStackItem(new VerificationTypeInfo(0, descriptor));
+                                       } else {
+                                               frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(descriptor, 1, descriptor.length - 1)));
+                                       }
+                                       pc += 3;
+                                       break;
+                               case Opcodes.OPC_putstatic:
+                                       frame.numberOfStackItems--;
+                                       pc += 3;
+                                       break;
+                               case Opcodes.OPC_getfield:
+                                       index = u2At(bytecodes, 1, pc);
+                                       nameAndTypeIndex = u2At(poolContents, 3,
+                                                       constantPoolOffsets[index]);
+                                       utf8index = u2At(poolContents, 3,
+                                                       constantPoolOffsets[nameAndTypeIndex]);
+                                       descriptor = utf8At(poolContents,
+                                                       constantPoolOffsets[utf8index] + 3, u2At(
+                                                                       poolContents, 1,
+                                                                       constantPoolOffsets[utf8index]));
+                                       frame.numberOfStackItems--;
+                                       if (descriptor.length == 1) {
+                                               // base type
+                                               switch(descriptor[0]) {
+                                                       case 'Z':
+                                                               frame.addStackItem(TypeBinding.BOOLEAN);
+                                                               break;
+                                                       case 'B':
+                                                               frame.addStackItem(TypeBinding.BYTE);
+                                                               break;
+                                                       case 'C':
+                                                               frame.addStackItem(TypeBinding.CHAR);
+                                                               break;
+                                                       case 'D':
+                                                               frame.addStackItem(TypeBinding.DOUBLE);
+                                                               break;
+                                                       case 'F':
+                                                               frame.addStackItem(TypeBinding.FLOAT);
+                                                               break;
+                                                       case 'I':
+                                                               frame.addStackItem(TypeBinding.INT);
+                                                               break;
+                                                       case 'J':
+                                                               frame.addStackItem(TypeBinding.LONG);
+                                                               break;
+                                                       case 'S':
+                                                               frame.addStackItem(TypeBinding.SHORT);
+                                                               break;
+                                               }
+                                       } else if (descriptor[0] == '[') {
+                                               frame.addStackItem(new VerificationTypeInfo(0, descriptor));
+                                       } else {
+                                               frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(descriptor, 1, descriptor.length - 1)));
+                                       }
+                                       pc += 3;
+                                       break;
+                               case Opcodes.OPC_putfield:
+                                       frame.numberOfStackItems -= 2;
+                                       pc += 3;
+                                       break;
+                               case Opcodes.OPC_invokevirtual:
+                                       index = u2At(bytecodes, 1, pc);
+                                       nameAndTypeIndex = u2At(poolContents, 3,
+                                                       constantPoolOffsets[index]);
+                                       utf8index = u2At(poolContents, 3,
+                                                       constantPoolOffsets[nameAndTypeIndex]);
+                                       descriptor = utf8At(poolContents,
+                                                       constantPoolOffsets[utf8index] + 3, u2At(
+                                                                       poolContents, 1,
+                                                                       constantPoolOffsets[utf8index]));
+                                       utf8index = u2At(poolContents, 1,
+                                                       constantPoolOffsets[nameAndTypeIndex]);
+                                       char[] name = utf8At(poolContents,
+                                                       constantPoolOffsets[utf8index] + 3, u2At(
+                                                                       poolContents, 1,
+                                                                       constantPoolOffsets[utf8index]));
+                                       frame.numberOfStackItems -= (getParametersCount(descriptor) + 1);
+                                       char[] returnType = getReturnType(descriptor);
+                                       if (returnType.length == 1) {
+                                               // base type
+                                               switch(returnType[0]) {
+                                                       case 'Z':
+                                                               frame.addStackItem(TypeBinding.BOOLEAN);
+                                                               break;
+                                                       case 'B':
+                                                               frame.addStackItem(TypeBinding.BYTE);
+                                                               break;
+                                                       case 'C':
+                                                               frame.addStackItem(TypeBinding.CHAR);
+                                                               break;
+                                                       case 'D':
+                                                               frame.addStackItem(TypeBinding.DOUBLE);
+                                                               break;
+                                                       case 'F':
+                                                               frame.addStackItem(TypeBinding.FLOAT);
+                                                               break;
+                                                       case 'I':
+                                                               frame.addStackItem(TypeBinding.INT);
+                                                               break;
+                                                       case 'J':
+                                                               frame.addStackItem(TypeBinding.LONG);
+                                                               break;
+                                                       case 'S':
+                                                               frame.addStackItem(TypeBinding.SHORT);
+                                                               break;
+                                               }
+                                       } else {
+                                               if (returnType[0] == '[') {
+                                                       frame.addStackItem(new VerificationTypeInfo(0, returnType));
+                                               } else {
+                                                       frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(returnType, 1, returnType.length - 1)));
+                                               }
+                                       }
+                                       pc += 3;
+                                       break;
+                               case Opcodes.OPC_invokedynamic:
+                                       index = u2At(bytecodes, 1, pc);
+                                       nameAndTypeIndex = u2At(poolContents, 3,
+                                                       constantPoolOffsets[index]);
+                                       utf8index = u2At(poolContents, 3,
+                                                       constantPoolOffsets[nameAndTypeIndex]);
+                                       descriptor = utf8At(poolContents,
+                                                       constantPoolOffsets[utf8index] + 3, u2At(
+                                                                       poolContents, 1,
+                                                                       constantPoolOffsets[utf8index]));
+                                       frame.numberOfStackItems -= getParametersCount(descriptor);
+                                       returnType = getReturnType(descriptor);
+                                       if (returnType.length == 1) {
+                                               // base type
+                                               switch(returnType[0]) {
+                                                       case 'Z':
+                                                               frame.addStackItem(TypeBinding.BOOLEAN);
+                                                               break;
+                                                       case 'B':
+                                                               frame.addStackItem(TypeBinding.BYTE);
+                                                               break;
+                                                       case 'C':
+                                                               frame.addStackItem(TypeBinding.CHAR);
+                                                               break;
+                                                       case 'D':
+                                                               frame.addStackItem(TypeBinding.DOUBLE);
+                                                               break;
+                                                       case 'F':
+                                                               frame.addStackItem(TypeBinding.FLOAT);
+                                                               break;
+                                                       case 'I':
+                                                               frame.addStackItem(TypeBinding.INT);
+                                                               break;
+                                                       case 'J':
+                                                               frame.addStackItem(TypeBinding.LONG);
+                                                               break;
+                                                       case 'S':
+                                                               frame.addStackItem(TypeBinding.SHORT);
+                                                               break;
+                                               }
+                                       } else {
+                                               if (returnType[0] == '[') {
+                                                       frame.addStackItem(new VerificationTypeInfo(0, returnType));
+                                               } else {
+                                                       frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(returnType, 1, returnType.length - 1)));
+                                               }
+                                       }
+                                       pc += 5;
+                                       break;
+                               case Opcodes.OPC_invokespecial:
+                                       index = u2At(bytecodes, 1, pc);
+                                       nameAndTypeIndex = u2At(poolContents, 3,
+                                                       constantPoolOffsets[index]);
+                                       utf8index = u2At(poolContents, 3,
+                                                       constantPoolOffsets[nameAndTypeIndex]);
+                                       descriptor = utf8At(poolContents,
+                                                       constantPoolOffsets[utf8index] + 3, u2At(
+                                                                       poolContents, 1,
+                                                                       constantPoolOffsets[utf8index]));
+                                       utf8index = u2At(poolContents, 1,
+                                                       constantPoolOffsets[nameAndTypeIndex]);
+                                       name = utf8At(poolContents,
+                                                       constantPoolOffsets[utf8index] + 3, u2At(
+                                                                       poolContents, 1,
+                                                                       constantPoolOffsets[utf8index]));
+                                       frame.numberOfStackItems -= getParametersCount(descriptor);
+                                       if (CharOperation.equals(ConstantPool.Init, name)) {
+                                               // constructor
+                                               frame.stackItems[frame.numberOfStackItems - 1].tag = VerificationTypeInfo.ITEM_OBJECT;
+                                       }
+                                       frame.numberOfStackItems--;
+                                       returnType = getReturnType(descriptor);
+                                       if (returnType.length == 1) {
+                                               // base type
+                                               switch(returnType[0]) {
+                                                       case 'Z':
+                                                               frame.addStackItem(TypeBinding.BOOLEAN);
+                                                               break;
+                                                       case 'B':
+                                                               frame.addStackItem(TypeBinding.BYTE);
+                                                               break;
+                                                       case 'C':
+                                                               frame.addStackItem(TypeBinding.CHAR);
+                                                               break;
+                                                       case 'D':
+                                                               frame.addStackItem(TypeBinding.DOUBLE);
+                                                               break;
+                                                       case 'F':
+                                                               frame.addStackItem(TypeBinding.FLOAT);
+                                                               break;
+                                                       case 'I':
+                                                               frame.addStackItem(TypeBinding.INT);
+                                                               break;
+                                                       case 'J':
+                                                               frame.addStackItem(TypeBinding.LONG);
+                                                               break;
+                                                       case 'S':
+                                                               frame.addStackItem(TypeBinding.SHORT);
+                                                               break;
+                                               }
+                                       } else {
+                                               if (returnType[0] == '[') {
+                                                       frame.addStackItem(new VerificationTypeInfo(0, returnType));
+                                               } else {
+                                                       frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(returnType, 1, returnType.length - 1)));
+                                               }
+                                       }
+                                       pc += 3;
+                                       break;
+                               case Opcodes.OPC_invokestatic:
+                                       index = u2At(bytecodes, 1, pc);
+                                       nameAndTypeIndex = u2At(poolContents, 3,
+                                                       constantPoolOffsets[index]);
+                                       utf8index = u2At(poolContents, 3,
+                                                       constantPoolOffsets[nameAndTypeIndex]);
+                                       descriptor = utf8At(poolContents,
+                                                       constantPoolOffsets[utf8index] + 3, u2At(
+                                                                       poolContents, 1,
+                                                                       constantPoolOffsets[utf8index]));
+                                       utf8index = u2At(poolContents, 1,
+                                                       constantPoolOffsets[nameAndTypeIndex]);
+                                       name = utf8At(poolContents,
+                                                       constantPoolOffsets[utf8index] + 3, u2At(
+                                                                       poolContents, 1,
+                                                                       constantPoolOffsets[utf8index]));
+                                       frame.numberOfStackItems -= getParametersCount(descriptor);
+                                       returnType = getReturnType(descriptor);
+                                       if (returnType.length == 1) {
+                                               // base type
+                                               switch(returnType[0]) {
+                                                       case 'Z':
+                                                               frame.addStackItem(TypeBinding.BOOLEAN);
+                                                               break;
+                                                       case 'B':
+                                                               frame.addStackItem(TypeBinding.BYTE);
+                                                               break;
+                                                       case 'C':
+                                                               frame.addStackItem(TypeBinding.CHAR);
+                                                               break;
+                                                       case 'D':
+                                                               frame.addStackItem(TypeBinding.DOUBLE);
+                                                               break;
+                                                       case 'F':
+                                                               frame.addStackItem(TypeBinding.FLOAT);
+                                                               break;
+                                                       case 'I':
+                                                               frame.addStackItem(TypeBinding.INT);
+                                                               break;
+                                                       case 'J':
+                                                               frame.addStackItem(TypeBinding.LONG);
+                                                               break;
+                                                       case 'S':
+                                                               frame.addStackItem(TypeBinding.SHORT);
+                                                               break;
+                                               }
+                                       } else {
+                                               if (returnType[0] == '[') {
+                                                       frame.addStackItem(new VerificationTypeInfo(0, returnType));
+                                               } else {
+                                                       frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(returnType, 1, returnType.length - 1)));
+                                               }
+                                       }
+                                       pc += 3;
+                                       break;
+                               case Opcodes.OPC_invokeinterface:
+                                       index = u2At(bytecodes, 1, pc);
+                                       nameAndTypeIndex = u2At(poolContents, 3,
+                                                       constantPoolOffsets[index]);
+                                       utf8index = u2At(poolContents, 3,
+                                                       constantPoolOffsets[nameAndTypeIndex]);
+                                       descriptor = utf8At(poolContents,
+                                                       constantPoolOffsets[utf8index] + 3, u2At(
+                                                                       poolContents, 1,
+                                                                       constantPoolOffsets[utf8index]));
+                                       utf8index = u2At(poolContents, 1,
+                                                       constantPoolOffsets[nameAndTypeIndex]);
+                                       name = utf8At(poolContents,
+                                                       constantPoolOffsets[utf8index] + 3, u2At(
+                                                                       poolContents, 1,
+                                                                       constantPoolOffsets[utf8index]));
+                                       // we don't need count and args
+                                       // u1At(bytecodes, 3, pc); // count
+                                       // u1At(bytecodes, 4, pc); // extra args
+                                       frame.numberOfStackItems -= (getParametersCount(descriptor) + 1);
+                                       returnType = getReturnType(descriptor);
+                                       if (returnType.length == 1) {
+                                               // base type
+                                               switch(returnType[0]) {
+                                                       case 'Z':
+                                                               frame.addStackItem(TypeBinding.BOOLEAN);
+                                                               break;
+                                                       case 'B':
+                                                               frame.addStackItem(TypeBinding.BYTE);
+                                                               break;
+                                                       case 'C':
+                                                               frame.addStackItem(TypeBinding.CHAR);
+                                                               break;
+                                                       case 'D':
+                                                               frame.addStackItem(TypeBinding.DOUBLE);
+                                                               break;
+                                                       case 'F':
+                                                               frame.addStackItem(TypeBinding.FLOAT);
+                                                               break;
+                                                       case 'I':
+                                                               frame.addStackItem(TypeBinding.INT);
+                                                               break;
+                                                       case 'J':
+                                                               frame.addStackItem(TypeBinding.LONG);
+                                                               break;
+                                                       case 'S':
+                                                               frame.addStackItem(TypeBinding.SHORT);
+                                                               break;
+                                               }
+                                       } else {
+                                               if (returnType[0] == '[') {
+                                                       frame.addStackItem(new VerificationTypeInfo(0, returnType));
+                                               } else {
+                                                       frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(returnType, 1, returnType.length - 1)));
+                                               }
+                                       }
+                                       pc += 5;
+                                       break;
+                               case Opcodes.OPC_new:
+                                       index = u2At(bytecodes, 1, pc);
+                                       utf8index = u2At(poolContents, 1,
+                                                       constantPoolOffsets[index]);
+                                       char[] className = utf8At(poolContents,
+                                                       constantPoolOffsets[utf8index] + 3, u2At(
+                                                                       poolContents, 1,
+                                                                       constantPoolOffsets[utf8index]));
+                                       VerificationTypeInfo verificationTypeInfo = new VerificationTypeInfo(0, VerificationTypeInfo.ITEM_UNINITIALIZED, className);
+                                       verificationTypeInfo.offset = currentPC;
+                                       frame.addStackItem(verificationTypeInfo);
+                                       pc += 3;
+                                       break;
+                               case Opcodes.OPC_newarray:
+                                       char[] constantPoolName = null;
+                                       switch (u1At(bytecodes, 1, pc)) {
+                                               case ClassFileConstants.INT_ARRAY :
+                                                       constantPoolName = new char[] { '[', 'I' };
+                                                       break;
+                                               case ClassFileConstants.BYTE_ARRAY :
+                                                       constantPoolName = new char[] { '[', 'B' };
+                                                       break;
+                                               case ClassFileConstants.BOOLEAN_ARRAY :
+                                                       constantPoolName = new char[] { '[', 'Z' };
+                                                       break;
+                                               case ClassFileConstants.SHORT_ARRAY :
+                                                       constantPoolName = new char[] { '[', 'S' };
+                                                       break;
+                                               case ClassFileConstants.CHAR_ARRAY :
+                                                       constantPoolName = new char[] { '[', 'C' };
+                                                       break;
+                                               case ClassFileConstants.LONG_ARRAY :
+                                                       constantPoolName = new char[] { '[', 'J' };
+                                                       break;
+                                               case ClassFileConstants.FLOAT_ARRAY :
+                                                       constantPoolName = new char[] { '[', 'F' };
+                                                       break;
+                                               case ClassFileConstants.DOUBLE_ARRAY :
+                                                       constantPoolName = new char[] { '[', 'D' };
+                                                       break;
+                                       }
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeIds.T_JavaLangObject, constantPoolName);
+                                       pc += 2;
+                                       break;
+                               case Opcodes.OPC_anewarray:
+                                       index = u2At(bytecodes, 1, pc);
+                                       utf8index = u2At(poolContents, 1,
+                                                       constantPoolOffsets[index]);
+                                       className = utf8At(poolContents,
+                                                       constantPoolOffsets[utf8index] + 3, u2At(
+                                                                       poolContents, 1,
+                                                                       constantPoolOffsets[utf8index]));
+                                       int classNameLength = className.length;
+                                       if (className[0] != '[') {
+                                               // this is a type name (class or interface). So we add appropriate '[', 'L' and ';'.
+                                               System.arraycopy(className, 0, (constantPoolName = new char[classNameLength + 3]), 2, classNameLength);
+                                               constantPoolName[0] = '[';
+                                               constantPoolName[1] = 'L';
+                                               constantPoolName[classNameLength + 2] = ';';
+                                       } else {
+                                               // if class name is already an array, we just need to add one dimension
+                                               System.arraycopy(className, 0, (constantPoolName = new char[classNameLength + 1]), 1, classNameLength);
+                                               constantPoolName[0] = '[';
+                                       }
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(0, constantPoolName);
+                                       pc += 3;
+                                       break;
+                               case Opcodes.OPC_arraylength:
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.INT);
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_athrow:
+                                       frame.numberOfStackItems--;
+                                       pc++;
+                                       addRealJumpTarget(realJumpTarget, pc - codeOffset);
+                                       break;
+                               case Opcodes.OPC_checkcast:
+                                       index = u2At(bytecodes, 1, pc);
+                                       utf8index = u2At(poolContents, 1,
+                                                       constantPoolOffsets[index]);
+                                       className = utf8At(poolContents,
+                                                       constantPoolOffsets[utf8index] + 3, u2At(
+                                                                       poolContents, 1,
+                                                                       constantPoolOffsets[utf8index]));
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(0, className);
+                                       pc += 3;
+                                       break;
+                               case Opcodes.OPC_instanceof:
+                                       // no need to know the class index = u2At(bytecodes, 1, pc);
+                                       frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.INT);
+                                       pc += 3;
+                                       break;
+                               case Opcodes.OPC_monitorenter:
+                               case Opcodes.OPC_monitorexit:
+                                       frame.numberOfStackItems--;
+                                       pc++;
+                                       break;
+                               case Opcodes.OPC_wide:
+                                       opcode = (byte) u1At(bytecodes, 1, pc);
+                                       if (opcode == Opcodes.OPC_iinc) {
+                                               // index = u2At(bytecodes, 2, pc);
+                                               // i2At(bytecodes, 4, pc); // const
+                                               // we don't need the index and the const value
+                                               pc += 6;
+                                       } else {
+                                               index = u2At(bytecodes, 2, pc);
+                                               // need to handle iload, fload, aload, lload, dload, istore, fstore, astore, lstore or dstore
+                                               switch(opcode) {
+                                                       case Opcodes.OPC_iload :
+                                                               frame.addStackItem(TypeBinding.INT);
+                                                               break;
+                                                       case Opcodes.OPC_fload :
+                                                               frame.addStackItem(TypeBinding.FLOAT);
+                                                               break;
+                                                       case Opcodes.OPC_aload :
+                                                               localsN = frame.locals[index];
+                                                               if (localsN == null) {
+                                                                       localsN = retrieveLocal(currentPC, index);
+                                                               }
+                                                               frame.addStackItem(localsN);
+                                                               break;
+                                                       case Opcodes.OPC_lload :
+                                                               frame.addStackItem(TypeBinding.LONG);
+                                                               break;
+                                                       case Opcodes.OPC_dload :
+                                                               frame.addStackItem(TypeBinding.DOUBLE);
+                                                               break;
+                                                       case Opcodes.OPC_istore :
+                                                               frame.numberOfStackItems--;
+                                                               break;
+                                                       case Opcodes.OPC_fstore :
+                                                               frame.numberOfStackItems--;
+                                                               break;
+                                                       case Opcodes.OPC_astore :
+                                                               frame.locals[index] = frame.stackItems[frame.numberOfStackItems - 1];
+                                                               frame.numberOfStackItems--;
+                                                               break;
+                                                       case Opcodes.OPC_lstore :
+                                                               frame.numberOfStackItems--;
+                                                               break;
+                                                       case Opcodes.OPC_dstore :
+                                                               frame.numberOfStackItems--;
+                                                               break;
+                                               }
+                                               pc += 4;
+                                       }
+                                       break;
+                               case Opcodes.OPC_multianewarray:
+                                       index = u2At(bytecodes, 1, pc);
+                                       utf8index = u2At(poolContents, 1,
+                                                       constantPoolOffsets[index]);
+                                       className = utf8At(poolContents,
+                                                       constantPoolOffsets[utf8index] + 3, u2At(
+                                                                       poolContents, 1,
+                                                                       constantPoolOffsets[utf8index]));
+                                       int dimensions = u1At(bytecodes, 3, pc); // dimensions
+                                       frame.numberOfStackItems -= dimensions;
+                                       classNameLength = className.length;
+                                       constantPoolName = new char[classNameLength + dimensions];
+                                       for (int i = 0; i < dimensions; i++) {
+                                               constantPoolName[i] = '[';
+                                       }
+                                       System.arraycopy(className, 0, constantPoolName, dimensions, classNameLength);
+                                       frame.addStackItem(new VerificationTypeInfo(0, constantPoolName));
+                                       pc += 4;
+                                       break;
+                               case Opcodes.OPC_ifnull:
+                               case Opcodes.OPC_ifnonnull:
+                                       frame.numberOfStackItems--;
+                                       addRealJumpTarget(realJumpTarget, currentPC + i2At(bytecodes, 1, pc));
+                                       pc += 3;
+                                       break;
+                               case Opcodes.OPC_goto_w:
+                                       addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 1, pc));
+                                       pc += 5;
+                                       addRealJumpTarget(realJumpTarget, pc - codeOffset); // handle infinite loop
+                                       break;
+                               default: // should not occur
+                                       if (this.codeStream.methodDeclaration != null) {
+                                               this.codeStream.methodDeclaration.scope.problemReporter().abortDueToInternalError(
+                                                               Messages.bind(
+                                                                               Messages.abort_invalidOpcode,
+                                                                               new Object[] {
+                                                                                               new Byte(opcode),
+                                                                                               new Integer(pc),
+                                                                                               new String(methodBinding.shortReadableName()),
+                                                                               }),
+                                                                               this.codeStream.methodDeclaration);
+                                       } else {
+                                               this.codeStream.lambdaExpression.scope.problemReporter().abortDueToInternalError(
+                                                               Messages.bind(
+                                                                               Messages.abort_invalidOpcode,
+                                                                               new Object[] {
+                                                                                               new Byte(opcode),
+                                                                                               new Integer(pc),
+                                                                                               new String(methodBinding.shortReadableName()),
+                                                                               }),
+                                                                               this.codeStream.lambdaExpression);
+                                       }
+                               break;
+                       }
+                       if (pc >= (codeLength + codeOffset)) {
+                               break;
+                       }
+               }
+               return filterFakeFrames(realJumpTarget, frames, codeLength);
+       }
+
+       private void addRealJumpTarget(Set realJumpTarget, int pc) {
+               realJumpTarget.add(new Integer(pc));
+       }
+       private void add(Map frames, StackMapFrame frame) {
+               frames.put(new Integer(frame.pc), frame);
+       }
+       private final int u1At(byte[] reference, int relativeOffset,
+                       int structOffset) {
+               return (reference[relativeOffset + structOffset] & 0xFF);
+       }
+
+       private final int u2At(byte[] reference, int relativeOffset,
+                       int structOffset) {
+               int position = relativeOffset + structOffset;
+               return ((reference[position++] & 0xFF) << 8)
+                               + (reference[position] & 0xFF);
+       }
+
+       private final long u4At(byte[] reference, int relativeOffset,
+                       int structOffset) {
+               int position = relativeOffset + structOffset;
+               return (((reference[position++] & 0xFFL) << 24)
+                               + ((reference[position++] & 0xFF) << 16)
+                               + ((reference[position++] & 0xFF) << 8) + (reference[position] & 0xFF));
+       }
+       // AspectJ Extension
+    void writeToContents(byte[] data) {
+      int N = data.length;
+         if (contentsOffset + N >= this.contents.length) {
+                       resizeContents(N);
+         }
+      System.arraycopy(data,0,contents,contentsOffset,N);
+      contentsOffset += N;
+    }
+    // End AspectJ Extension    
+
+       private final int i2At(byte[] reference, int relativeOffset, int structOffset) {
+               int position = relativeOffset + structOffset;
+               return (reference[position++] << 8) + (reference[position] & 0xFF);
+       }
+
+       public char[] utf8At(byte[] reference, int absoluteOffset,
+                       int bytesAvailable) {
+               int length = bytesAvailable;
+               char outputBuf[] = new char[bytesAvailable];
+               int outputPos = 0;
+               int readOffset = absoluteOffset;
+
+               while (length != 0) {
+                       int x = reference[readOffset++] & 0xFF;
+                       length--;
+                       if ((0x80 & x) != 0) {
+                               if ((x & 0x20) != 0) {
+                                       length -= 2;
+                                       x = ((x & 0xF) << 12)
+                                                       | ((reference[readOffset++] & 0x3F) << 6)
+                                                       | (reference[readOffset++] & 0x3F);
+                               } else {
+                                       length--;
+                                       x = ((x & 0x1F) << 6) | (reference[readOffset++] & 0x3F);
+                               }
+                       }
+                       outputBuf[outputPos++] = (char) x;
+               }
+
+               if (outputPos != bytesAvailable) {
+                       System.arraycopy(outputBuf, 0, (outputBuf = new char[outputPos]),
+                                       0, outputPos);
+               }
+               return outputBuf;
+       }
+}
index e022d1c45f7d448fdfeb994333074dafaf8a20b3..57129c8532e50cf949b85bc2e2dc6079634fb792 100644 (file)
@@ -25,6 +25,7 @@ public class AjcTest {
        private static boolean is16VMOrGreater = false;
        private static boolean is17VMOrGreater = false;
        private static boolean is18VMOrGreater = false;
+       private static boolean is19VMOrGreater = false;
        
        static { // matching logic is also in org.aspectj.util.LangUtil
         String vm = System.getProperty("java.version"); // JLS 20.18.7
@@ -46,6 +47,12 @@ public class AjcTest {
                        is16VMOrGreater = true;
                        is17VMOrGreater = true;
                        is18VMOrGreater = true;
+               } else if (vm.startsWith("1.9")) {
+                       is15VMOrGreater = true;
+                       is16VMOrGreater = true;
+                       is17VMOrGreater = true;
+                       is18VMOrGreater = true;
+                       is19VMOrGreater = true;
                }
        }
 
@@ -89,6 +96,7 @@ public class AjcTest {
                if (vmLevel.equals("1.6")) canRun = is16VMOrGreater;
                if (vmLevel.equals("1.7")) canRun = is17VMOrGreater;
                if (vmLevel.equals("1.8")) canRun = is18VMOrGreater;
+               if (vmLevel.equals("1.9")) canRun = is19VMOrGreater;
                if (!canRun) {
                        System.out.println("***SKIPPING TEST***" + getTitle()+ " needs " + getVmLevel() 
                                        + ", currently running on " + System.getProperty("java.vm.version"));
index 179779f130c8f648da57e0dcc04ef5a95cc90db1..1930f369b4f8a37dfe5a10f7012debfe5304a322 100644 (file)
@@ -11,7 +11,7 @@
        <classpathentry combineaccessrules="false" kind="src" path="/aspectj5rt"/>
        <classpathentry kind="lib" path="/lib/commons/commons.jar" sourcepath="/lib/commons/commons-src.zip"/>
        <classpathentry kind="lib" path="/lib/bcel/bcel.jar" sourcepath="/lib/bcel/bcel-src.zip"/>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
        <classpathentry combineaccessrules="false" kind="src" path="/org.aspectj.matcher"/>
        <classpathentry kind="lib" path="/lib/asm/asm-5.0.1.renamed.jar"/>
        <classpathentry kind="output" path="bin"/>
diff --git a/weaver/.settings/org.eclipse.jdt.core.prefs b/weaver/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..7341ab1
--- /dev/null
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.7
index 83b7efdac9ca776d85865d22e092cb2926844ca8..8d9bed8834c42eb468ebd46148b81e6f149ac35e 100644 (file)
 
 package org.aspectj.weaver.bcel;
 
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.URI;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.Iterator;
@@ -59,7 +67,7 @@ public class ClassPathManager {
                        trace.enter("<init>", this, new Object[] { classpath, handler });
                entries = new ArrayList<Entry>();
                for (Iterator<String> i = classpath.iterator(); i.hasNext();) {
-                       String name = (String) i.next();
+                       String name = i.next();
                        addPath(name, handler);
                }
                if (trace.isTraceEnabled())
@@ -69,6 +77,10 @@ public class ClassPathManager {
        protected ClassPathManager() {
        }
 
+       private static URI JRT_URI = URI.create("jrt:/"); //$NON-NLS-1$
+
+       private static String JAVA_BASE_PATH = "java.base"; //$NON-NLS-1$
+       
        public void addPath(String name, IMessageHandler handler) {
                File f = new File(name);
                String lc = name.toLowerCase();
@@ -83,7 +95,12 @@ public class ClassPathManager {
                                return;
                        }
                        try {
-                               entries.add(new ZipFileEntry(f));
+                               if (lc.endsWith(".jimage")) {
+                                       // Java9
+                                       entries.add(new JImageEntry(f));
+                               } else {
+                                       entries.add(new ZipFileEntry(f));
+                               }
                        } catch (IOException ioe) {
                                MessageUtil.warn(handler, WeaverMessages.format(WeaverMessages.ZIPFILE_ENTRY_INVALID, name, ioe.getMessage()));
                                return;
@@ -103,6 +120,7 @@ public class ClassPathManager {
                                        return ret;
                        } catch (IOException ioe) {
                                // this is NOT an error: it's valid to have missing classpath entries
+                               ioe.printStackTrace();
                                i.remove();
                        }
 
@@ -154,6 +172,41 @@ public class ClassPathManager {
 
                // public abstract List getAllClassFiles() throws IOException;
        }
+       
+       private static class ByteBasedClassFile extends ClassFile {
+
+               private byte[] bytes;
+               private ByteArrayInputStream bais;
+               private String path;
+               
+               public ByteBasedClassFile(byte[] bytes, String path) {
+                       this.bytes = bytes;                     
+                       this.path = path;
+               }
+               
+               @Override
+               public InputStream getInputStream() throws IOException {
+                       this.bais = new ByteArrayInputStream(bytes);
+                       return this.bais;
+               }
+
+               @Override
+               public String getPath() {
+                       return this.path;
+               }
+
+               @Override
+               public void close() {
+                       if (this.bais!=null) {
+                               try {
+                                       this.bais.close();
+                               } catch (IOException e) {
+                               }
+                               this.bais = null;
+                       }
+               }
+               
+       }
 
        private static class FileClassFile extends ClassFile {
                private File file;
@@ -243,6 +296,77 @@ public class ClassPathManager {
                }
 
        }
+       
+       public class JImageEntry extends Entry {
+               private FileSystem fs;
+               
+               public JImageEntry(File file) {
+                       fs = FileSystems.getFileSystem(JRT_URI);
+//                     Iterable<java.nio.file.Path> roots = fs.getRootDirectories();
+//                     java.nio.file.Path basePath = null;
+//                     try {
+//                             System.err.println("Find on javax.naming.Context: "+find("javax.naming.Context"));
+//                     } catch (IOException e) {
+//                             // TODO Auto-generated catch block
+//                             e.printStackTrace();
+//                     }
+//                     roots: for (java.nio.file.Path path : roots) {
+//                             System.err.println(">>"+path);
+//                             try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(path)) {
+//                                     for (java.nio.file.Path subdir: stream) {
+//                                             System.err.println(">>>"+subdir);
+////                                           if (subdir.toString().indexOf(JAVA_BASE_PATH) != -1) {
+////                                                   basePath = subdir;
+////                                                   break roots;
+////                                           }
+//                                 }
+//                             } catch (Exception e) {
+//                                     e.printStackTrace();
+//                             }
+//                     }
+               }
+               
+               @Override
+               public ClassFile find(String name) throws IOException {
+                       String fileName = name.replace('.', '/') + ".class";
+                       try {
+                               Path p = fs.getPath(JAVA_BASE_PATH,fileName);
+                               byte[] bs = Files.readAllBytes(p);
+                               return new ByteBasedClassFile(bs, fileName);
+                       } catch (NoSuchFileException nsfe) {
+                               // try other modules!
+                               Iterable<java.nio.file.Path> roots = fs.getRootDirectories();
+                               for (java.nio.file.Path path : roots) {
+                                       DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(path);
+                                       try {
+                                               for (java.nio.file.Path module: stream) {
+                                               try {
+                                                               Path p = fs.getPath(module.toString(),fileName);
+                                                               byte[] bs = Files.readAllBytes(p);
+                                                               return new ByteBasedClassFile(bs, fileName);
+                                               } catch (NoSuchFileException nsfe2) {
+                                               }
+                                               }
+                                       } finally {
+                                               stream.close();
+                                       }
+                               }
+                               return null;                    
+                       }
+               }
+               
+               public ClassFile find(String module, String name) throws IOException {
+                       String fileName = name.replace('.', '/') + ".class";
+                       try {
+                               Path p = fs.getPath(module,fileName);
+                               byte[] bs = Files.readAllBytes(p);
+                               return new ByteBasedClassFile(bs, fileName);
+                       } catch (NoSuchFileException nsfe) {
+                               return null;                    
+                       }
+               }
+
+       }
 
        public class ZipFileEntry extends Entry {
                private File file;