• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License.  Alternatively, the contents of this file may be used under
8  * the terms of the GNU Lesser General Public License Version 2.1 or later,
9  * or the Apache License Version 2.0.
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  */
16 
17 package javassist;
18 
19 import javassist.bytecode.BadBytecode;
20 import javassist.bytecode.CodeAttribute;
21 import javassist.bytecode.CodeIterator;
22 import javassist.bytecode.ConstPool;
23 import javassist.bytecode.MethodInfo;
24 import javassist.convert.TransformAccessArrayField;
25 import javassist.convert.TransformAfter;
26 import javassist.convert.TransformBefore;
27 import javassist.convert.TransformCall;
28 import javassist.convert.TransformFieldAccess;
29 import javassist.convert.TransformNew;
30 import javassist.convert.TransformNewClass;
31 import javassist.convert.TransformReadField;
32 import javassist.convert.TransformWriteField;
33 import javassist.convert.Transformer;
34 
35 /**
36  * Simple translator of method bodies
37  * (also see the <code>javassist.expr</code> package).
38  *
39  * <p>Instances of this class specifies how to instrument of the
40  * bytecodes representing a method body.  They are passed to
41  * <code>CtClass.instrument()</code> or
42  * <code>CtMethod.instrument()</code> as a parameter.
43  *
44  * <p>Example:
45  * <pre>
46  * ClassPool cp = ClassPool.getDefault();
47  * CtClass point = cp.get("Point");
48  * CtClass singleton = cp.get("Singleton");
49  * CtClass client = cp.get("Client");
50  * CodeConverter conv = new CodeConverter();
51  * conv.replaceNew(point, singleton, "makePoint");
52  * client.instrument(conv);
53  * </pre>
54  *
55  * <p>This program substitutes "<code>Singleton.makePoint()</code>"
56  * for all occurrences of "<code>new Point()</code>"
57  * appearing in methods declared in a <code>Client</code> class.
58  *
59  * @see javassist.CtClass#instrument(CodeConverter)
60  * @see javassist.CtMethod#instrument(CodeConverter)
61  * @see javassist.expr.ExprEditor
62  */
63 public class CodeConverter {
64     protected Transformer transformers = null;
65 
66     /**
67      * Modify a method body so that instantiation of the specified class
68      * is replaced with a call to the specified static method.  For example,
69      * <code>replaceNew(ctPoint, ctSingleton, "createPoint")</code>
70      * (where <code>ctPoint</code> and <code>ctSingleton</code> are
71      * compile-time classes for class <code>Point</code> and class
72      * <code>Singleton</code>, respectively)
73      * replaces all occurrences of:
74      *
75      * <pre>new Point(x, y)</pre>
76      *
77      * in the method body with:
78      *
79      * <pre>Singleton.createPoint(x, y)</pre>
80      *
81      * <p>This enables to intercept instantiation of <code>Point</code>
82      * and change the samentics.  For example, the following
83      * <code>createPoint()</code> implements the singleton pattern:
84      *
85      * <pre>public static Point createPoint(int x, int y) {
86      *     if (aPoint == null)
87      *         aPoint = new Point(x, y);
88      *     return aPoint;
89      * }
90      * </pre>
91      *
92      * <p>The static method call substituted for the original <code>new</code>
93      * expression must be
94      * able to receive the same set of parameters as the original
95      * constructor.  If there are multiple constructors with different
96      * parameter types, then there must be multiple static methods
97      * with the same name but different parameter types.
98      *
99      * <p>The return type of the substituted static method must be
100      * the exactly same as the type of the instantiated class specified by
101      * <code>newClass</code>.
102      *
103      * @param newClass          the instantiated class.
104      * @param calledClass       the class in which the static method is
105      *                          declared.
106      * @param calledMethod      the name of the static method.
107      */
replaceNew(CtClass newClass, CtClass calledClass, String calledMethod)108     public void replaceNew(CtClass newClass,
109                            CtClass calledClass, String calledMethod) {
110         transformers = new TransformNew(transformers, newClass.getName(),
111                                         calledClass.getName(), calledMethod);
112     }
113 
114     /**
115      * Modify a method body so that instantiation of the class
116      * specified by <code>oldClass</code>
117      * is replaced with instantiation of another class <code>newClass</code>.
118      * For example,
119      * <code>replaceNew(ctPoint, ctPoint2)</code>
120      * (where <code>ctPoint</code> and <code>ctPoint2</code> are
121      * compile-time classes for class <code>Point</code> and class
122      * <code>Point2</code>, respectively)
123      * replaces all occurrences of:
124      *
125      * <pre>new Point(x, y)</pre>
126      *
127      * in the method body with:
128      *
129      * <pre>new Point2(x, y)</pre>
130      *
131      * <p>Note that <code>Point2</code> must be type-compatible with <code>Point</code>.
132      * It must have the same set of methods, fields, and constructors as the
133      * replaced class.
134      */
replaceNew(CtClass oldClass, CtClass newClass)135     public void replaceNew(CtClass oldClass, CtClass newClass) {
136         transformers = new TransformNewClass(transformers, oldClass.getName(),
137                                              newClass.getName());
138     }
139 
140     /**
141      * Modify a method body so that field read/write expressions access
142      * a different field from the original one.
143      *
144      * <p>Note that this method changes only the filed name and the class
145      * declaring the field; the type of the target object does not change.
146      * Therefore, the substituted field must be declared in the same class
147      * or a superclass of the original class.
148      *
149      * <p>Also, <code>clazz</code> and <code>newClass</code> must specify
150      * the class directly declaring the field.  They must not specify
151      * a subclass of that class.
152      *
153      * @param field             the originally accessed field.
154      * @param newClass  the class declaring the substituted field.
155      * @param newFieldname      the name of the substituted field.
156      */
redirectFieldAccess(CtField field, CtClass newClass, String newFieldname)157     public void redirectFieldAccess(CtField field,
158                                     CtClass newClass, String newFieldname) {
159         transformers = new TransformFieldAccess(transformers, field,
160                                                 newClass.getName(),
161                                                 newFieldname);
162     }
163 
164     /**
165      * Modify a method body so that an expression reading the specified
166      * field is replaced with a call to the specified <i>static</i> method.
167      * This static method receives the target object of the original
168      * read expression as a parameter.  It must return a value of
169      * the same type as the field.
170      *
171      * <p>For example, the program below
172      *
173      * <pre>Point p = new Point();
174      * int newX = p.x + 3;</pre>
175      *
176      * <p>can be translated into:
177      *
178      * <pre>Point p = new Point();
179      * int newX = Accessor.readX(p) + 3;</pre>
180      *
181      * <p>where
182      *
183      * <pre>public class Accessor {
184      *     public static int readX(Object target) { ... }
185      * }</pre>
186      *
187      * <p>The type of the parameter of <code>readX()</code> must
188      * be <code>java.lang.Object</code> independently of the actual
189      * type of <code>target</code>.  The return type must be the same
190      * as the field type.
191      *
192      * @param field             the field.
193      * @param calledClass       the class in which the static method is
194      *                          declared.
195      * @param calledMethod      the name of the static method.
196      */
replaceFieldRead(CtField field, CtClass calledClass, String calledMethod)197     public void replaceFieldRead(CtField field,
198                                  CtClass calledClass, String calledMethod) {
199         transformers = new TransformReadField(transformers, field,
200                                               calledClass.getName(),
201                                               calledMethod);
202     }
203 
204     /**
205      * Modify a method body so that an expression writing the specified
206      * field is replaced with a call to the specified static method.
207      * This static method receives two parameters: the target object of
208      * the original
209      * write expression and the assigned value.  The return type of the
210      * static method is <code>void</code>.
211      *
212      * <p>For example, the program below
213      *
214      * <pre>Point p = new Point();
215      * p.x = 3;</pre>
216      *
217      * <p>can be translated into:
218      *
219      * <pre>Point p = new Point();
220      * Accessor.writeX(3);</pre>
221      *
222      * <p>where
223      *
224      * <pre>public class Accessor {
225      *     public static void writeX(Object target, int value) { ... }
226      * }</pre>
227      *
228      * <p>The type of the first parameter of <code>writeX()</code> must
229      * be <code>java.lang.Object</code> independently of the actual
230      * type of <code>target</code>.  The type of the second parameter
231      * is the same as the field type.
232      *
233      * @param field             the field.
234      * @param calledClass       the class in which the static method is
235      *                          declared.
236      * @param calledMethod      the name of the static method.
237      */
replaceFieldWrite(CtField field, CtClass calledClass, String calledMethod)238     public void replaceFieldWrite(CtField field,
239                                   CtClass calledClass, String calledMethod) {
240         transformers = new TransformWriteField(transformers, field,
241                                                calledClass.getName(),
242                                                calledMethod);
243     }
244 
245     /**
246      * Modify a method body, so that ALL accesses to an array are replaced with
247      * calls to static methods within another class. In the case of reading an
248      * element from the array, this is replaced with a call to a static method with
249      * the array and the index as arguments, the return value is the value read from
250      * the array. If writing to an array, this is replaced with a call to a static
251      * method with the array, index and new value as parameters, the return value of
252      * the static method is <code>void</code>.
253      *
254      * <p>The <code>calledClass</code> parameter is the class containing the static methods to be used
255      * for array replacement. The <code>names</code> parameter points to an implementation of
256      * <code>ArrayAccessReplacementMethodNames</code> which specifies the names of the method to be
257      * used for access for each type of array.  For example reading from an <code>int[]</code> will
258      * require a different method than if writing to an <code>int[]</code>, and writing to a <code>long[]</code>
259      * will require a different method than if writing to a <code>byte[]</code>. If the implementation
260      * of <code>ArrayAccessReplacementMethodNames</code> does not contain the name for access for a
261      * type of array, that access is not replaced.
262      *
263      * <p>A default implementation of <code>ArrayAccessReplacementMethodNames</code> called
264      * <code>DefaultArrayAccessReplacementMethodNames</code> has been provided and is what is used in the
265      * following example. This also assumes that <code>'foo.ArrayAdvisor'</code> is the name of the
266      * <code>CtClass</code> passed in.
267      *
268      * <p>If we have the following class:
269      * <pre>class POJO{
270      *    int[] ints = new int[]{1, 2, 3, 4, 5};
271      *    long[] longs = new int[]{10, 20, 30};
272      *    Object objects = new Object[]{true, false};
273      *    Integer[] integers = new Integer[]{new Integer(10)};
274      * }
275      * </pre>
276      * and this is accessed as:
277      * <pre>POJO p = new POJO();
278      *
279      * //Write to int array
280      * p.ints[2] = 7;
281      *
282      * //Read from int array
283      * int i = p.ints[2];
284      *
285      * //Write to long array
286      * p.longs[2] = 1000L;
287      *
288      * //Read from long array
289      * long l = p.longs[2];
290      *
291      * //Write to Object array
292      * p.objects[2] = "Hello";
293      *
294      * //Read from Object array
295      * Object o = p.objects[2];
296      *
297      * //Write to Integer array
298      * Integer integer = new Integer(5);
299      * p.integers[0] = integer;
300      *
301      * //Read from Object array
302      * integer = p.integers[0];
303      * </pre>
304      *
305      * Following instrumentation we will have
306      * <pre>POJO p = new POJO();
307      *
308      * //Write to int array
309      * ArrayAdvisor.arrayWriteInt(p.ints, 2, 7);
310      *
311      * //Read from int array
312      * int i = ArrayAdvisor.arrayReadInt(p.ints, 2);
313      *
314      * //Write to long array
315      * ArrayAdvisor.arrayWriteLong(p.longs, 2, 1000L);
316      *
317      * //Read from long array
318      * long l = ArrayAdvisor.arrayReadLong(p.longs, 2);
319      *
320      * //Write to Object array
321      * ArrayAdvisor.arrayWriteObject(p.objects, 2, "Hello");
322      *
323      * //Read from Object array
324      * Object o = ArrayAdvisor.arrayReadObject(p.objects, 2);
325      *
326      * //Write to Integer array
327      * Integer integer = new Integer(5);
328      * ArrayAdvisor.arrayWriteObject(p.integers, 0, integer);
329      *
330      * //Read from Object array
331      * integer = ArrayAdvisor.arrayWriteObject(p.integers, 0);
332      * </pre>
333      *
334      * @see DefaultArrayAccessReplacementMethodNames
335      *
336      * @param calledClass        the class containing the static methods.
337      * @param names              contains the names of the methods to replace
338      *                           the different kinds of array access with.
339      */
replaceArrayAccess(CtClass calledClass, ArrayAccessReplacementMethodNames names)340     public void replaceArrayAccess(CtClass calledClass, ArrayAccessReplacementMethodNames names)
341         throws NotFoundException
342     {
343        transformers = new TransformAccessArrayField(transformers, calledClass.getName(), names);
344     }
345 
346     /**
347      * Modify method invocations in a method body so that a different
348      * method will be invoked.
349      *
350      * <p>Note that the target object, the parameters, or
351      * the type of invocation
352      * (static method call, interface call, or private method call)
353      * are not modified.  Only the method name is changed.  The substituted
354      * method must have the same signature that the original one has.
355      * If the original method is a static method, the substituted method
356      * must be static.
357      *
358      * @param origMethod        original method
359      * @param substMethod       substituted method
360      */
redirectMethodCall(CtMethod origMethod, CtMethod substMethod)361     public void redirectMethodCall(CtMethod origMethod,
362                                    CtMethod substMethod)
363         throws CannotCompileException
364     {
365         String d1 = origMethod.getMethodInfo2().getDescriptor();
366         String d2 = substMethod.getMethodInfo2().getDescriptor();
367         if (!d1.equals(d2))
368             throw new CannotCompileException("signature mismatch: "
369                                              + substMethod.getLongName());
370 
371         int mod1 = origMethod.getModifiers();
372         int mod2 = substMethod.getModifiers();
373         if (Modifier.isStatic(mod1) != Modifier.isStatic(mod2)
374             || (Modifier.isPrivate(mod1) && !Modifier.isPrivate(mod2))
375             || origMethod.getDeclaringClass().isInterface()
376                != substMethod.getDeclaringClass().isInterface())
377             throw new CannotCompileException("invoke-type mismatch "
378                                              + substMethod.getLongName());
379 
380         transformers = new TransformCall(transformers, origMethod,
381                                          substMethod);
382     }
383 
384     /**
385      * Correct invocations to a method that has been renamed.
386      * If a method is renamed, calls to that method must be also
387      * modified so that the method with the new name will be called.
388      *
389      * <p>The method must be declared in the same class before and
390      * after it is renamed.
391      *
392      * <p>Note that the target object, the parameters, or
393      * the type of invocation
394      * (static method call, interface call, or private method call)
395      * are not modified.  Only the method name is changed.
396      *
397      * @param oldMethodName        the old name of the method.
398      * @param newMethod            the method with the new name.
399      * @see javassist.CtMethod#setName(String)
400      */
redirectMethodCall(String oldMethodName, CtMethod newMethod)401     public void redirectMethodCall(String oldMethodName,
402                                    CtMethod newMethod)
403         throws CannotCompileException
404     {
405         transformers
406             = new TransformCall(transformers, oldMethodName, newMethod);
407     }
408 
409     /**
410      * Insert a call to another method before an existing method call.
411      * That "before" method must be static.  The return type must be
412      * <code>void</code>.  As parameters, the before method receives
413      * the target object and all the parameters to the originally invoked
414      * method.  For example, if the originally invoked method is
415      * <code>move()</code>:
416      *
417      * <pre>class Point {
418      *     Point move(int x, int y) { ... }
419      * }</pre>
420      *
421      * <p>Then the before method must be something like this:
422      *
423      * <pre>class Verbose {
424      *     static void print(Point target, int x, int y) { ... }
425      * }</pre>
426      *
427      * <p>The <code>CodeConverter</code> would translate bytecode
428      * equivalent to:
429      *
430      * <pre>Point p2 = p.move(x + y, 0);</pre>
431      *
432      * <p>into the bytecode equivalent to:
433      *
434      * <pre>int tmp1 = x + y;
435      * int tmp2 = 0;
436      * Verbose.print(p, tmp1, tmp2);
437      * Point p2 = p.move(tmp1, tmp2);</pre>
438      *
439      * @param origMethod        the method originally invoked.
440      * @param beforeMethod      the method invoked before
441      *                          <code>origMethod</code>.
442      */
insertBeforeMethod(CtMethod origMethod, CtMethod beforeMethod)443     public void insertBeforeMethod(CtMethod origMethod,
444                                    CtMethod beforeMethod)
445         throws CannotCompileException
446     {
447         try {
448             transformers = new TransformBefore(transformers, origMethod,
449                                                beforeMethod);
450         }
451         catch (NotFoundException e) {
452             throw new CannotCompileException(e);
453         }
454     }
455 
456     /**
457      * Inserts a call to another method after an existing method call.
458      * That "after" method must be static.  The return type must be
459      * <code>void</code>.  As parameters, the after method receives
460      * the target object and all the parameters to the originally invoked
461      * method.  For example, if the originally invoked method is
462      * <code>move()</code>:
463      *
464      * <pre>class Point {
465      *     Point move(int x, int y) { ... }
466      * }</pre>
467      *
468      * <p>Then the after method must be something like this:
469      *
470      * <pre>class Verbose {
471      *     static void print(Point target, int x, int y) { ... }
472      * }</pre>
473      *
474      * <p>The <code>CodeConverter</code> would translate bytecode
475      * equivalent to:
476      *
477      * <pre>Point p2 = p.move(x + y, 0);</pre>
478      *
479      * <p>into the bytecode equivalent to:
480      *
481      * <pre>
482      * int tmp1 = x + y;
483      * int tmp2 = 0;
484      * Point p2 = p.move(tmp1, tmp2);
485      * Verbose.print(p, tmp1, tmp2);</pre>
486      *
487      * @param origMethod        the method originally invoked.
488      * @param afterMethod       the method invoked after
489      *                          <code>origMethod</code>.
490      */
insertAfterMethod(CtMethod origMethod, CtMethod afterMethod)491     public void insertAfterMethod(CtMethod origMethod,
492                                   CtMethod afterMethod)
493         throws CannotCompileException
494     {
495         try {
496             transformers = new TransformAfter(transformers, origMethod,
497                                                afterMethod);
498         }
499         catch (NotFoundException e) {
500             throw new CannotCompileException(e);
501         }
502     }
503 
504     /**
505      * Performs code conversion.
506      */
doit(CtClass clazz, MethodInfo minfo, ConstPool cp)507     protected void doit(CtClass clazz, MethodInfo minfo, ConstPool cp)
508         throws CannotCompileException
509     {
510        Transformer t;
511         CodeAttribute codeAttr = minfo.getCodeAttribute();
512         if (codeAttr == null || transformers == null)
513             return;
514         for (t = transformers; t != null; t = t.getNext())
515             t.initialize(cp, clazz, minfo);
516 
517         CodeIterator iterator = codeAttr.iterator();
518         while (iterator.hasNext()) {
519             try {
520                 int pos = iterator.next();
521                 for (t = transformers; t != null; t = t.getNext())
522                     pos = t.transform(clazz, pos, iterator, cp);
523             }
524             catch (BadBytecode e) {
525                 throw new CannotCompileException(e);
526             }
527         }
528 
529         int locals = 0;
530         int stack = 0;
531         for (t = transformers; t != null; t = t.getNext()) {
532             int s = t.extraLocals();
533             if (s > locals)
534                 locals = s;
535 
536             s = t.extraStack();
537             if (s > stack)
538                 stack = s;
539         }
540 
541         for (t = transformers; t != null; t = t.getNext())
542             t.clean();
543 
544         if (locals > 0)
545             codeAttr.setMaxLocals(codeAttr.getMaxLocals() + locals);
546 
547         if (stack > 0)
548             codeAttr.setMaxStack(codeAttr.getMaxStack() + stack);
549 
550         try {
551         	minfo.rebuildStackMapIf6(clazz.getClassPool(),
552                                      clazz.getClassFile2());
553         }
554         catch (BadBytecode b) {
555             throw new CannotCompileException(b.getMessage(), b);
556         }
557     }
558 
559     /**
560      * Interface containing the method names to be used
561      * as array access replacements.
562      *
563      * @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
564      * @version $Revision: 1.16 $
565      */
566     public interface ArrayAccessReplacementMethodNames
567     {
568        /**
569         * Returns the name of a static method with the signature
570         * <code>(Ljava/lang/Object;I)B</code> to replace reading from a byte[].
571         */
byteOrBooleanRead()572        String byteOrBooleanRead();
573 
574        /**
575         * Returns the name of a static method with the signature
576         * <code>(Ljava/lang/Object;IB)V</code> to replace writing to a byte[].
577         */
byteOrBooleanWrite()578        String byteOrBooleanWrite();
579 
580        /**
581         * @return the name of a static method with the signature
582         * <code>(Ljava/lang/Object;I)C</code> to replace reading from a char[].
583         */
charRead()584        String charRead();
585 
586        /**
587         * Returns the name of a static method with the signature
588         * <code>(Ljava/lang/Object;IC)V</code> to replace writing to a byte[].
589         */
charWrite()590        String charWrite();
591 
592        /**
593         * Returns the name of a static method with the signature
594         * <code>(Ljava/lang/Object;I)D</code> to replace reading from a double[].
595         */
doubleRead()596        String doubleRead();
597 
598        /**
599         * Returns the name of a static method with the signature
600         * <code>(Ljava/lang/Object;ID)V</code> to replace writing to a double[].
601         */
doubleWrite()602        String doubleWrite();
603 
604        /**
605         * Returns the name of a static method with the signature
606         * <code>(Ljava/lang/Object;I)F</code> to replace reading from a float[].
607         */
floatRead()608        String floatRead();
609 
610        /**
611         * Returns the name of a static method with the signature
612         * <code>(Ljava/lang/Object;IF)V</code> to replace writing to a float[].
613         */
floatWrite()614        String floatWrite();
615 
616        /**
617         * Returns the name of a static method with the signature
618         * <code>(Ljava/lang/Object;I)I</code> to replace reading from a int[].
619         */
intRead()620        String intRead();
621 
622        /**
623         * Returns the name of a static method with the signature
624         * <code>(Ljava/lang/Object;II)V</code> to replace writing to a int[].
625         */
intWrite()626        String intWrite();
627 
628        /**
629         * Returns the name of a static method with the signature
630         * <code>(Ljava/lang/Object;I)J</code> to replace reading from a long[].
631         */
longRead()632        String longRead();
633 
634        /**
635         * Returns the name of a static method with the signature
636         * <code>(Ljava/lang/Object;IJ)V</code> to replace writing to a long[].
637         */
longWrite()638        String longWrite();
639 
640        /**
641         * Returns the name of a static method with the signature
642         * <code>(Ljava/lang/Object;I)Ljava/lang/Object;</code>
643         * to replace reading from a Object[] (or any subclass of object).
644         */
objectRead()645        String objectRead();
646 
647        /**
648         * Returns the name of a static method with the signature
649         * <code>(Ljava/lang/Object;ILjava/lang/Object;)V</code>
650         * to replace writing to a Object[] (or any subclass of object).
651         */
objectWrite()652        String objectWrite();
653 
654        /**
655         * Returns the name of a static method with the signature
656         * <code>(Ljava/lang/Object;I)S</code> to replace reading from a short[].
657         */
shortRead()658        String shortRead();
659 
660        /**
661         * Returns the name of a static method with the signature
662         * <code>(Ljava/lang/Object;IS)V</code> to replace writing to a short[].
663         */
shortWrite()664        String shortWrite();
665     }
666 
667     /**
668      * Default implementation of the <code>ArrayAccessReplacementMethodNames</code>
669      * interface giving default values for method names to be used for replacing
670      * accesses to array elements.
671      *
672      * @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
673      * @version $Revision: 1.16 $
674      */
675     public static class DefaultArrayAccessReplacementMethodNames
676         implements ArrayAccessReplacementMethodNames
677     {
678        /**
679         * Returns "arrayReadByteOrBoolean" as the name of the static method with the signature
680         * (Ljava/lang/Object;I)B to replace reading from a byte[].
681         */
682         @Override
byteOrBooleanRead()683        public String byteOrBooleanRead()
684        {
685           return "arrayReadByteOrBoolean";
686        }
687 
688        /**
689         * Returns "arrayWriteByteOrBoolean" as the name of the static method with the signature
690         * (Ljava/lang/Object;IB)V  to replace writing to a byte[].
691         */
692         @Override
byteOrBooleanWrite()693        public String byteOrBooleanWrite()
694        {
695           return "arrayWriteByteOrBoolean";
696        }
697 
698        /**
699         * Returns "arrayReadChar" as the name of the static method with the signature
700         * (Ljava/lang/Object;I)C  to replace reading from a char[].
701         */
702         @Override
charRead()703        public String charRead()
704        {
705           return "arrayReadChar";
706        }
707 
708        /**
709         * Returns "arrayWriteChar" as the name of the static method with the signature
710         * (Ljava/lang/Object;IC)V to replace writing to a byte[].
711         */
712         @Override
charWrite()713        public String charWrite()
714        {
715           return "arrayWriteChar";
716        }
717 
718        /**
719         * Returns "arrayReadDouble" as the name of the static method with the signature
720         * (Ljava/lang/Object;I)D to replace reading from a double[].
721         */
722         @Override
doubleRead()723        public String doubleRead()
724        {
725           return "arrayReadDouble";
726        }
727 
728        /**
729         * Returns "arrayWriteDouble" as the name of the static method with the signature
730         * (Ljava/lang/Object;ID)V to replace writing to a double[].
731         */
732         @Override
doubleWrite()733        public String doubleWrite()
734        {
735           return "arrayWriteDouble";
736        }
737 
738        /**
739         * Returns "arrayReadFloat" as the name of the static method with the signature
740         * (Ljava/lang/Object;I)F  to replace reading from a float[].
741         */
742         @Override
floatRead()743        public String floatRead()
744        {
745           return "arrayReadFloat";
746        }
747 
748        /**
749         * Returns "arrayWriteFloat" as the name of the static method with the signature
750         * (Ljava/lang/Object;IF)V  to replace writing to a float[].
751         */
752         @Override
floatWrite()753        public String floatWrite()
754        {
755           return "arrayWriteFloat";
756        }
757 
758        /**
759         * Returns "arrayReadInt" as the name of the static method with the signature
760         * (Ljava/lang/Object;I)I to replace reading from a int[].
761         */
762         @Override
intRead()763        public String intRead()
764        {
765           return "arrayReadInt";
766        }
767 
768        /**
769         * Returns "arrayWriteInt" as the name of the static method with the signature
770         * (Ljava/lang/Object;II)V to replace writing to a int[].
771         */
772         @Override
intWrite()773        public String intWrite()
774        {
775           return "arrayWriteInt";
776        }
777 
778        /**
779         * Returns "arrayReadLong" as the name of the static method with the signature
780         * (Ljava/lang/Object;I)J to replace reading from a long[].
781         */
782         @Override
longRead()783        public String longRead()
784        {
785           return "arrayReadLong";
786        }
787 
788        /**
789         * Returns "arrayWriteLong" as the name of the static method with the signature
790         * (Ljava/lang/Object;IJ)V to replace writing to a long[].
791         */
792         @Override
longWrite()793        public String longWrite()
794        {
795           return "arrayWriteLong";
796        }
797 
798        /**
799         * Returns "arrayReadObject" as the name of the static method with the signature
800         * (Ljava/lang/Object;I)Ljava/lang/Object;  to replace reading from a Object[] (or any subclass of object).
801         */
802         @Override
objectRead()803        public String objectRead()
804        {
805           return "arrayReadObject";
806        }
807 
808        /**
809         * Returns "arrayWriteObject" as the name of the static method with the signature
810         * (Ljava/lang/Object;ILjava/lang/Object;)V  to replace writing to a Object[] (or any subclass of object).
811         */
812         @Override
objectWrite()813        public String objectWrite()
814        {
815           return "arrayWriteObject";
816        }
817 
818        /**
819         * Returns "arrayReadShort" as the name of the static method with the signature
820         * (Ljava/lang/Object;I)S to replace reading from a short[].
821         */
822         @Override
shortRead()823        public String shortRead()
824        {
825           return "arrayReadShort";
826        }
827 
828        /**
829         * Returns "arrayWriteShort" as the name of the static method with the signature
830         * (Ljava/lang/Object;IS)V to replace writing to a short[].
831         */
832         @Override
shortWrite()833        public String shortWrite()
834        {
835           return "arrayWriteShort";
836        }
837     }
838 }
839