Project Report: fawkez

Packagesummary org.jcoderz.commons.tracing

org.jcoderz.commons.tracing.MethodTracingInjector

LineHitsNoteSource
1  /*
2   * $Id: ArraysUtil.java 1011 2008-06-16 17:57:36Z amandel $
3   *
4   * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5   *
6   * Redistribution and use in source and binary forms, with or without
7   * modification, are permitted provided that the following conditions are
8   * met:
9   *
10   *    * Redistributions of source code must retain the above copyright
11   *      notice, this list of conditions and the following disclaimer.
12   *    * Redistributions in binary form must reproduce the above
13   *      copyright notice, this list of conditions and the following
14   *      disclaimer in the documentation and/or other materials
15   *      provided with the distribution.
16   *    * Neither the name of the jCoderZ.org Project nor the names of
17   *      its contributors may be used to endorse or promote products
18   *      derived from this software without specific prior written
19   *      permission.
20   *
21   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24   * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25   * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28   * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32   */
33  package org.jcoderz.commons.tracing;
34  
35  import java.util.ArrayList;
36  import java.util.Iterator;
37  import java.util.logging.Level;
38  import java.util.logging.Logger;
39  
40  import org.jcoderz.commons.util.Assert;
41  import org.objectweb.asm.Opcodes;
42  import org.objectweb.asm.Type;
43  import org.objectweb.asm.tree.AbstractInsnNode;
44  import org.objectweb.asm.tree.FieldInsnNode;
45  import org.objectweb.asm.tree.InsnList;
46  import org.objectweb.asm.tree.InsnNode;
47  import org.objectweb.asm.tree.JumpInsnNode;
48  import org.objectweb.asm.tree.LabelNode;
49  import org.objectweb.asm.tree.LdcInsnNode;
50  import org.objectweb.asm.tree.LineNumberNode;
51  import org.objectweb.asm.tree.LocalVariableNode;
52  import org.objectweb.asm.tree.MethodInsnNode;
53  import org.objectweb.asm.tree.MethodNode;
54  import org.objectweb.asm.tree.TryCatchBlockNode;
55  import org.objectweb.asm.tree.TypeInsnNode;
56  import org.objectweb.asm.tree.VarInsnNode;
57  
58  /**
59   * Takes care to add Tracing to the methods.
60   * @author mandelan
61   */
62  public class MethodTracingInjector
63  {
640   private static final String CLASSNAME
65      = MethodTracingInjector.class.getName();
660   private static final Logger logger
67      = Logger.getLogger(CLASSNAME);
68    private static final String JAVA_LOGGER = "java/util/logging/Logger";
69  
70    /** Link to the class injector where this method belongs to. */
71    private final ClassTracingInjector mClassInjector;
72    /** The asm MethodNode of the method under injection. */
73    private final MethodNode mMethodNode;
74    /** Method name as it is used in the logger calls. */
75    private final String mMethodName;
76    /** The local variable that is used to sore the is loggable boolean. */
77    private LocalVariableNode mIsLoggableVar;
78    /** Method start label - after logging injection */
79    private LabelNode mMethodStart;
80    /**
81     * Method start label - before logging injection - after the
82     * isLoggable assignment.
83     */
84    private LabelNode mOldMethodStart;
85    /** Label at the very end of the method. */
86    private LabelNode mMethodEnd;
87  
88    /**
89     * Create a new MethodTracingInjector.
90     * @param mn the method node where to inject the tracing logging.
91     * @param ci the class injector where this method belongs to
92     */
93 (1)  public MethodTracingInjector(MethodNode mn, ClassTracingInjector ci)
940   {
950     mClassInjector = ci;
960     mMethodNode = mn;
970     mMethodName = mn.name;
980   }
99  
100    /**
101     * Do the job.
102     */
103    public void inject ()
104    {
105      // NO abstract nor native methods
1060     if ((mMethodNode.access
107          & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_NATIVE)) == 0)
108      {
1090(2)      int lineNumber = getLineNumber();
1100       if (logger.isLoggable(Level.FINEST))
111        {
1120         logger.finest("Injecting tracing into "
113              + AsmUtil.toString(mMethodNode) + "at line " + lineNumber
114              + '.');
115        }
1160       mMethodStart = new LabelNode();
1170       mOldMethodStart = getOrCreateStartLabel();
1180       mMethodEnd = getOrCreateEndLabel();
119  
120  
1210       final InsnList cmd = new InsnList();
1220       cmd.add(mMethodStart);
1230       if (lineNumber != -1)
124        {
1250         cmd.add(new LineNumberNode(lineNumber - 1, mMethodStart));
126        }
1270       if ("<clinit>".equals(mMethodNode.name))
128        { // Refactor??
1290         mClassInjector.injectStaticLoggerMember(cmd);
130        }
131  
1320       ensureLocalVariablesAreSet();
133  
134        // Create boolean method var isLoggable....
1350       injectIsLoggableVariable(cmd);
136  
1370       final LabelNode labelAfterEnteringLogging = isLoggable(cmd);
1380       injectEnteringLogging(cmd);
1390       cmd.add(labelAfterEnteringLogging);
140  
141        // TAKE CARE FOR LABEL!
142        // Must be shifted down for tryCatchBlocks
143        // MUST stay for Variables -> Move Variables!
144        // fix var map:
1450       final Iterator i = mMethodNode.localVariables.iterator();
1460       while (i.hasNext())
147        {
1480         final LocalVariableNode var = (LocalVariableNode) i.next();
149  
1500         if (var.start.equals(mOldMethodStart))
151          {
1520           var.start = mMethodStart;
153          }
1540       }
1550       mMethodNode.instructions.insertBefore(mOldMethodStart, cmd);
1560       cmd.clear();
157  
1580       final TryCatchBlockNode tryCatch
159          = injectThrowingLogging(cmd,
160            labelAfterEnteringLogging);
1610       if (tryCatch != null)
162        {
1630         mMethodNode.tryCatchBlocks.add(tryCatch);
1640         mMethodNode.instructions.insertBefore(mMethodEnd, cmd);
165        }
1660       cmd.clear();
167  
1680       injectExitingLogger();
1690     }
170      else
171      {
1720       if (logger.isLoggable(Level.FINEST))
173        {
1740         logger.finest("No tracing in native / abstract methods! "
175              + AsmUtil.toString(mMethodNode));
176        }
177      }
1780   }
179  
180 (3)  private int getLineNumber()
181    {
1820     int result = -1;
1830     final Iterator i = mMethodNode.instructions.iterator();
1840     while (i.hasNext())
185      {
1860(4)      final AbstractInsnNode current = (AbstractInsnNode) i.next();
1870       if (current.getType() == AbstractInsnNode.LINE)
188        {
1890         final LineNumberNode lineNumber = (LineNumberNode) current;
1900         result = lineNumber.line;
1910         break;
192        }
1930     }
1940     return result;
195    }
196  
197 (5)(6)  private int getLastLineNumber()
198    {
1990     int result = -1;
2000     final Iterator i = mMethodNode.instructions.iterator();
2010     while (i.hasNext())
202      {
2030(7)      final AbstractInsnNode current = (AbstractInsnNode) i.next();
2040       if (current.getType() == AbstractInsnNode.LINE)
205        {
2060         final LineNumberNode lineNumber = (LineNumberNode) current;
2070         result = Math.max(lineNumber.line, result);
208        }
2090     }
2100     return result;
211    }
212  
213 (8)  private void injectEnteringLogging(InsnList cmd)
214    {
215      // Check arguments
216      final Type[] arguments;
2170     if (mMethodNode.desc != null)
218      {
2190       arguments = Type.getArgumentTypes(mMethodNode.desc);
220      }
221      else
222      {
2230       arguments = new Type[0];
224      }
225  
2260     mClassInjector.getStaticLoggerOnStack(cmd);
2270     mClassInjector.getClassNameOnStack(cmd);
2280     getMethodNameOnStack(cmd);
2290     if (arguments == null || arguments.length == 0)
230      {
2310       cmd.add(new MethodInsnNode(
232            Opcodes.INVOKEVIRTUAL,
233            JAVA_LOGGER,
234            "entering",
235            "(Ljava/lang/String;Ljava/lang/String;)V"));
236      }
2370     else if (arguments.length == 1)
238      {
2390       boxMe(cmd, isStatic() ? 0 : 1, arguments[0]);
2400       cmd.add(new MethodInsnNode(
241            Opcodes.INVOKEVIRTUAL,
242            JAVA_LOGGER,
243            "entering",
244            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V"));
245      }
246      else
247      {
2480       AsmUtil.loadConstant(cmd, arguments.length);
2490       cmd.add(new TypeInsnNode(Opcodes.ANEWARRAY, "java/lang/Object"));
250  
2510       final int[] argPos = getArguments(arguments);
2520       for (int i = 0; i < arguments.length; i++)
253        {
2540         cmd.add(new InsnNode(Opcodes.DUP));
2550         AsmUtil.loadConstant(cmd, i);
2560         boxMe(cmd, argPos[i], arguments[i]);
2570         cmd.add(new InsnNode(Opcodes.AASTORE));
258        }
2590       cmd.add(new MethodInsnNode(
260            Opcodes.INVOKEVIRTUAL,
261            JAVA_LOGGER,
262            "entering",
263            "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V"));
264      }
2650   }
266  
267 (9)  private void injectExitingLogger()
268    {
2690     final Iterator i = mMethodNode.instructions.iterator();
2700     while (i.hasNext())
271      {
2720(10)      final AbstractInsnNode current = (AbstractInsnNode) i.next();
2730       final int opcode = current.getOpcode();
274  
2750       LabelNode labelAfterLogging = null;
2760       InsnList cmd = null;
2770       switch (opcode)
278        {
279          case Opcodes.RETURN:
2800           cmd = new InsnList();
2810           labelAfterLogging = isLoggable(cmd);
2820           mClassInjector.getStaticLoggerOnStack(cmd);
2830           mClassInjector.getClassNameOnStack(cmd);
2840           getMethodNameOnStack(cmd);
2850           cmd.add(new MethodInsnNode(
286                Opcodes.INVOKEVIRTUAL,
287                JAVA_LOGGER,
288                "exiting",
289                "(Ljava/lang/String;Ljava/lang/String;)V"));
2900           cmd.add(labelAfterLogging);
2910           mMethodNode.instructions.insertBefore(current, cmd);
2920           break;
293          case Opcodes.IRETURN:
294          case Opcodes.LRETURN:
295          case Opcodes.FRETURN:
296          case Opcodes.DRETURN:
297          case Opcodes.ARETURN:
2980           cmd = new InsnList();
2990           final Type type = Type.getReturnType(mMethodNode.desc);
3000           labelAfterLogging = isLoggable(cmd);
3010           final LocalVariableNode resultVar
302              = storeTypeOnStackInNewVariable(cmd, labelAfterLogging,
303                type);
304  
3050           mClassInjector.getStaticLoggerOnStack(cmd);
3060           mClassInjector.getClassNameOnStack(cmd);
3070           getMethodNameOnStack(cmd);
308  
3090           boxMe(cmd, resultVar);
3100           cmd.add(new MethodInsnNode(
311                Opcodes.INVOKEVIRTUAL,
312                JAVA_LOGGER,
313                "exiting",
314                "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V"));
3150           cmd.add(labelAfterLogging);
3160           mMethodNode.instructions.insertBefore(current, cmd);
3170           break;
318          default:
319            // stepping forward in method
320            break;
321        }
3220     }
3230   }
324  
325 (11)  private TryCatchBlockNode injectThrowingLogging(InsnList cmd,
326        LabelNode labelAfterEnteringLogging)
327    {
3280     final LabelNode lastStatement = beforeLastStatement();
3290     TryCatchBlockNode result = null;
3300     if (!near(lastStatement, labelAfterEnteringLogging))
331      {
3320       final LabelNode methodEnd = new LabelNode();
3330       cmd.add(methodEnd);
3340       final LabelNode labelAfterThrowingLogging = isLoggable(cmd);
335  
336  
3370       final LocalVariableNode exVar
338          = storeTypeOnStackInNewVariable(
339              cmd, labelAfterThrowingLogging, TracingInjector.THROWABLE_TYPE);
340  
3410       mClassInjector.getStaticLoggerOnStack(cmd);
3420       mClassInjector.getClassNameOnStack(cmd);
3430       getMethodNameOnStack(cmd);
3440       cmd.add(new VarInsnNode(Opcodes.ALOAD, exVar.index));
3450       cmd.add(new MethodInsnNode(
346                  Opcodes.INVOKEVIRTUAL,
347                  JAVA_LOGGER,
348                  "throwing",
349 (12)                "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)V"));
3500       cmd.add(labelAfterThrowingLogging);
351  
3520       cmd.add(new InsnNode(Opcodes.ATHROW));
3530       final LabelNode theEnd = new LabelNode();
3540       cmd.add(theEnd);
355    // mIsLoggableVar.end = theEnd;
356  
3570       result  = new TryCatchBlockNode(labelAfterEnteringLogging,
358            lastStatement, methodEnd,
359            TracingInjector.THROWABLE_TYPE.getInternalName());
360      }
3610     return result;
362    }
363  
364    /**
365     * Checks if the 2 labels are near to each other (not separated by code).
366     * @return true if the 2 labels are near to each other
367     */
368 (13)  private boolean near(LabelNode labelA, LabelNode labelB)
369    {
3700     boolean result = false;
3710(14)    AbstractInsnNode a = labelA;
3720(15)    while (a != null &&
373 (16)        ( a.getType() == AbstractInsnNode.LABEL
374              || a.getType() == AbstractInsnNode.LINE))
375      {
3760       if (a == labelB)
377        {
3780         result = true;
3790         break;
380        }
3810       a = a.getNext();
382      }
3830     if (!result)
384      {
3850       a = labelA;
3860(17)      while (a != null &&
387 (18)          ( a.getType() == AbstractInsnNode.LABEL
388                || a.getType() == AbstractInsnNode.LINE))
389        {
3900         if (a == labelB)
391          {
3920           result = true;
3930           break;
394          }
3950         a = a.getPrevious();
396        }
397      }
3980     return result;
399    }
400  
401 (19)(20)  private LabelNode beforeLastStatement()
402    {
4030(21)    AbstractInsnNode last = mMethodNode.instructions.getLast();
404  
4050(22)    while (last != null &&
406          (last.getType() == AbstractInsnNode.LINE
407              || last.getType() == AbstractInsnNode.LABEL))
408      {
4090       last = last.getPrevious();
410      }
411  
412      // now check for a label...
4130(23)    AbstractInsnNode label
414        = (last == null ? mMethodNode.instructions.getLast() : last);
4150     while (label != null && label.getType() == AbstractInsnNode.LINE)
416      {
4170       label = label.getPrevious();
418      }
419  
420      final LabelNode result;
4210     if (label != null && label.getType() == AbstractInsnNode.LABEL)
422      {
4230       result = (LabelNode) label;
424      }
4250     else if (last == null)
426      {
4270       result = new LabelNode();
4280       mMethodNode.instructions.insert(result);
429      }
430      else
431      {
4320       result = new LabelNode();
4330       mMethodNode.instructions.insertBefore(last, result);
434      }
4350     return result;
436    }
437  
438    /**
439     *
440     */
441 (24)  private void ensureLocalVariablesAreSet()
442    {
4430     if (mMethodNode.localVariables == null)
444      {
4450       mMethodNode.localVariables = new ArrayList();
446      }
4470   }
448  
449    private void injectIsLoggableVariable (InsnList cmd)
450    {
4510     final int varIndex = getFreeLocalIndex();
452  
4530     final LabelNode varStartNode = new LabelNode();
4540     mIsLoggableVar
455        = new LocalVariableNode(
456            TracingInjector.IS_LOGGABLE_FIELD_NAME + varIndex,
457            Type.BOOLEAN_TYPE.getDescriptor(),
458            (String) null, varStartNode, mMethodEnd, varIndex);
4590     mMethodNode.localVariables.add(mIsLoggableVar);
460  
4610     mClassInjector.getStaticLoggerOnStack(cmd);
4620     cmd.add(new FieldInsnNode(
463          Opcodes.GETSTATIC,
464          "java/util/logging/Level",
465          "FINER", "Ljava/util/logging/Level;"));
4660     cmd.add(new MethodInsnNode(
467          Opcodes.INVOKEVIRTUAL,
468          JAVA_LOGGER,
469          "isLoggable",
470          "(Ljava/util/logging/Level;)Z"));
4710     cmd.add(new VarInsnNode(Opcodes.ISTORE, mIsLoggableVar.index));
4720     cmd.add(varStartNode);
4730   }
474  
475    /**
476     * Returns an array holding the Variable index of the corresponding Argument.
477     * @param types an array holding the argument Types.
478     * @return
479     */
480 (25)  private int[] getArguments(Type[] types)
481    {
4820     final int[] result = new int[types.length];
4830     int cur = isStatic() ? 0 : 1;
4840     for (int pos = 0; pos < types.length; pos++)
485      {
4860       result[pos] = cur;
4870       cur += types[pos].getSize();
488      }
4890     return result;
490    }
491  
492    /**
493     *
494     * @param cmd
495    */
496 (26)  private void getMethodNameOnStack(InsnList cmd)
497    {
4980     cmd.add(new LdcInsnNode(mMethodName));
4990   }
500  
501    /**
502     *
503     * @return
504     */
505    private int getFreeLocalIndex ()
506    {
5070     final Iterator i = mMethodNode.localVariables.iterator();
5080     int maxIndex = -1;
5090     while (i.hasNext())
510      {
5110       final LocalVariableNode node = (LocalVariableNode) i.next();
5120       if (node.index >= maxIndex)
513          // >= needed because index could be reused with larger type
514        {
5150         if (node.desc.equals(Type.DOUBLE_TYPE.getDescriptor())
516              || node.desc.equals(Type.LONG_TYPE.getDescriptor()))
517          {
5180           maxIndex = node.index + 1;
519          }
520          else
521          {
5220           maxIndex = node.index;
523          }
524        }
5250     }
5260     maxIndex++;
527  
5280     final int other = getFreeLocalByCode();
5290     return Math.max(other, maxIndex);
530    }
531  
532    /**
533     *
534     * @return
535     */
536 (27)  private int getFreeLocalByCode ()
537    {
5380      int maxIndex = -1;
5390      final Iterator i = mMethodNode.instructions.iterator();
5400      while (i.hasNext())
541       {
5420(28)       final AbstractInsnNode insn = (AbstractInsnNode) i.next();
5430        if (insn instanceof VarInsnNode)
544         {
5450          final VarInsnNode varInsnNode = (VarInsnNode) insn;
5460          if (varInsnNode.var >= maxIndex)
547           { // >= needed because index could be reused with larger type
5480            switch (varInsnNode.getOpcode())
549             {
550               case Opcodes.ILOAD:
551               case Opcodes.FLOAD:
552               case Opcodes.ALOAD:
553               case Opcodes.ISTORE:
554               case Opcodes.FSTORE:
555               case Opcodes.ASTORE:
5560                maxIndex = varInsnNode.var;
5570                break;
558  
559               case Opcodes.LLOAD:
560               case Opcodes.DLOAD:
561               case Opcodes.LSTORE:
562               case Opcodes.DSTORE:
5630                maxIndex = varInsnNode.var + 1;
5640                break;
565               case Opcodes.RET:
566                 // ignore already covered with the ASTORE
5670                break;
568               default:
5690                Assert.assertTrue(
570                     "Unexpected opcode " + insn.getOpcode()
571                     + " in VarInsnNode operation.", false);
572               break;
573             }
574           }
575         }
5760      }
577  
5780      return maxIndex + 1;
579    }
580  
581    /**
582     * Expects data of type type on the Stacks and stores it in a new Variable,
583     * the stack content stays unchanged!
584     * @param cmd the instruction list to add the commands.
585     * @param end intended end label for the validity of the variable
586     * @param type the type of the data to store
587     * @return the new generated variable
588     */
589 (29)  private LocalVariableNode storeTypeOnStackInNewVariable(InsnList cmd,
590        LabelNode end, final Type type)
591    {
592 (30)    // TODO: Could be more efficient in reusing free indexes
593      // But we can not relay on the localVariables table...
594  
595      // CREATE VAR
596      // The label is the position AFTER the xSTORE cmd.
5970     final LabelNode startLabel = new LabelNode();
5980     final int index = getFreeLocalIndex();
5990     final LocalVariableNode resultVar
600        = new LocalVariableNode(
601            TracingInjector.RESULT_VAR_FIELD_NAME + index,
602          type.getDescriptor(), (String) null, startLabel, end,
603          index);
6040     mMethodNode.localVariables.add(resultVar);
605  
606      // CREATE CODE
6070     cmd.add(new InsnNode(type.getSize() == 1 ? Opcodes.DUP : Opcodes.DUP2));
6080     cmd.add(new VarInsnNode(
609          type.getOpcode(Opcodes.ISTORE), resultVar.index));
6100     cmd.add(startLabel);
611      // Load the var again (could use the DUP above)
612  //    cmd.add(new VarInsnNode(
613  //        type.getOpcode(Opcodes.ILOAD), resultVar.index));
6140     return resultVar;
615    }
616  
617    /**
618     *
619     * @return
620     */
621    private boolean isStatic ()
622    {
6230     return (mMethodNode.access & Opcodes.ACC_STATIC) != 0;
624    }
625  
626    /**
627     *
628     * @param cmd
629    * @param var
630    */
631 (31)  private void boxMe(InsnList cmd, LocalVariableNode var)
632    {
6330     Assert.notNull(cmd, "cmd");
6340     Assert.notNull(var, "var");
6350     boxMe(cmd, var.index, Type.getType(var.desc));
6360   }
637  
638    /**
639     *
640     * @param cmd
641    * @param index
642    * @param type
643    */
644 (32)  private void boxMe(InsnList cmd, int index, Type type)
645    {
6460     switch (type.getSort())
647      {
648        case Type.SHORT:
6490         boxMe(cmd, type, "java/lang/Short", index);
6500         break;
651        case Type.INT:
6520         boxMe(cmd, type, "java/lang/Integer", index);
6530         break;
654        case Type.CHAR:
6550         boxMe(cmd, type, "java/lang/Character", index);
6560         break;
657        case Type.BOOLEAN:
6580         boxMe(cmd, type, "java/lang/Boolean", index);
6590         break;
660        case Type.LONG:
6610         boxMe(cmd, type, "java/lang/Long", index);
6620         break;
663        case Type.FLOAT:
6640         boxMe(cmd, type, "java/lang/Float", index);
6650         break;
666        case Type.DOUBLE:
6670         boxMe(cmd, type, "java/lang/Double", index);
6680         break;
669        case Type.BYTE:
6700         boxMe(cmd, type, "java/lang/Byte", index);
6710         break;
672        case Type.ARRAY:
673        case Type.OBJECT:
6740         cmd.add(new VarInsnNode(
675              type.getOpcode(Opcodes.ILOAD), index));
6760         break;
677        default:
6780         throw new RuntimeException("Unexpected type " + type.getDescriptor());
679      }
6800   }
681  
682    /**
683     *
684     * @param instr
685    * @param type
686    * @param boxClassName
687    * @param index
688    */
689 (33)  private void boxMe(InsnList instr, Type type, String boxClassName,
690        int index)
691    {
6920     if (!(type.getSort() == Type.BOOLEAN) && !mClassInjector.isJava5())
693      {
694        // new Xxxxx(...)
6950       instr.add(new TypeInsnNode(Opcodes.NEW, boxClassName));
6960       instr.add(new InsnNode(Opcodes.DUP));
6970       instr.add(new VarInsnNode(type.getOpcode(Opcodes.ILOAD), index));
6980       instr.add(new MethodInsnNode(
699          Opcodes.INVOKESPECIAL, boxClassName, "<init>",
700          "(" + type.getDescriptor() + ")V"));
701      }
702      else
703      { // since JDK 1.5 version (except for boolean):
704        // Xxxxx.valueOf(...)
7050       instr.add(new VarInsnNode(
706          type.getOpcode(Opcodes.ILOAD), index));
7070       instr.add(new MethodInsnNode(
708            Opcodes.INVOKESTATIC, boxClassName, "valueOf",
709            "(" + type.getDescriptor() + ")L" + boxClassName + ";"));
710      }
7110   }
712  
713    /**
714     *
715     * @return
716     */
717    private LabelNode getOrCreateEndLabel ()
718    {
7190(34)    final AbstractInsnNode last = mMethodNode.instructions.getLast();
720      final LabelNode result;
7210     if (last.getType() == AbstractInsnNode.LABEL)
722      {
7230       result = (LabelNode) last;
724      }
725      else
726      {
727        // need a new end Label...
7280       result = new LabelNode();
7290       mMethodNode.instructions.add(result);
730      }
7310     return result;
732    }
733  
734    /**
735     *
736     * @return
737     */
738    private LabelNode getOrCreateStartLabel ()
739    {
7400(35)    final AbstractInsnNode first = mMethodNode.instructions.getFirst();
741      final LabelNode result;
7420     if (first.getType() == AbstractInsnNode.LABEL)
743      {
7440       result = (LabelNode) first;
745      }
746      else
747      { // need a start Label...
7480       result = new LabelNode();
7490       mMethodNode.instructions.insertBefore(first, result);
750      }
7510     return result;
752    }
753  
754    /**
755     * Create ifLoggable code and return a label to jump to
756     * in case of a false result.
757     * @param cmd the instruction list to add the instructions to.
758     * @return the node that is used as target if the isLoggable
759     *  evaluates to false.
760     */
761    private LabelNode isLoggable (InsnList cmd)
762    {
7630     cmd.add(new VarInsnNode(Opcodes.ILOAD, mIsLoggableVar.index));
7640     final LabelNode afterLogging = new LabelNode();
7650     cmd.add(new JumpInsnNode(Opcodes.IFEQ, afterLogging));
7660     return afterLogging;
767    }
768  }

Findings in this File

c (1) 93 : 31 '(' is not preceded with whitespace.
c (2) 109 : 11 Variable 'lineNumber' should be declared final.
c (3) 180 : 28 '(' is not preceded with whitespace.
c (4) 186 : 13 Declaring variables, return values or parameters of type 'AbstractInsnNode' is not allowed.
c (5) 197 : 32 '(' is not preceded with whitespace.
i (6) 197 : 15 Avoid unused private methods such as 'getLastLineNumber()'.
c (7) 203 : 13 Declaring variables, return values or parameters of type 'AbstractInsnNode' is not allowed.
c (8) 213 : 37 '(' is not preceded with whitespace.
c (9) 267 : 35 '(' is not preceded with whitespace.
c (10) 272 : 13 Declaring variables, return values or parameters of type 'AbstractInsnNode' is not allowed.
c (11) 325 : 50 '(' is not preceded with whitespace.
c (12) 349 : 0 Line is longer than 80 characters.
c (13) 368 : 23 '(' is not preceded with whitespace.
c (14) 371 : 5 Declaring variables, return values or parameters of type 'AbstractInsnNode' is not allowed.
c (15) 372 : 22 '&&' should be on a new line.
c (16) 373 : 10 '(' is followed by whitespace.
c (17) 386 : 24 '&&' should be on a new line.
c (18) 387 : 12 '(' is followed by whitespace.
c (19) 401 : 40 '(' is not preceded with whitespace.
c (20) 401 : 11 The method beforeLastStatement() has an NPath complexity of 240
c (21) 403 : 5 Declaring variables, return values or parameters of type 'AbstractInsnNode' is not allowed.
c (22) 405 : 25 '&&' should be on a new line.
c (23) 413 : 5 Declaring variables, return values or parameters of type 'AbstractInsnNode' is not allowed.
c (24) 441 : 42 '(' is not preceded with whitespace.
c (25) 480 : 29 '(' is not preceded with whitespace.
c (26) 496 : 36 '(' is not preceded with whitespace.
c (27) 536 : 3 Cyclomatic Complexity is 15 (max allowed is 12).
c (28) 542 : 14 Declaring variables, return values or parameters of type 'AbstractInsnNode' is not allowed.
c (29) 589 : 58 '(' is not preceded with whitespace.
i (30) 592 : 0 Comment matches to-do format '(TODO|FIXME|CHECKME)'.
c (31) 631 : 21 '(' is not preceded with whitespace.
c (32) 644 : 21 '(' is not preceded with whitespace.
c (33) 689 : 21 '(' is not preceded with whitespace.
c (34) 719 : 11 Declaring variables, return values or parameters of type 'AbstractInsnNode' is not allowed.
c (35) 740 : 11 Declaring variables, return values or parameters of type 'AbstractInsnNode' is not allowed.