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