22 *
23 */
24
25 import java.io.*;
26 import java.lang.reflect.*;
27 import java.util.jar.*;
28
29 public class Util {
30 /**
31 * Invoke the loader.defineClass() class method to define the class stored in clsFile,
32 * with the following modification:
33 * <ul>
34 * <li> All ASCII strings in the class file bytes that matches fromString will be replaced with toString.
35 * NOTE: the two strings must be the exact same length.
36 * </ul>
37 */
38 public static Class defineModifiedClass(ClassLoader loader, File clsFile, String fromString, String toString)
39 throws FileNotFoundException, IOException, NoSuchMethodException, IllegalAccessException,
40 InvocationTargetException
41 {
42 DataInputStream dis = new DataInputStream(new FileInputStream(clsFile));
43 byte[] buff = new byte[(int)clsFile.length()];
44 dis.readFully(buff);
45 replace(buff, fromString, toString);
46
47 System.out.println("Loading from: " + clsFile + " (" + buff.length + " bytes)");
48
49 Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass",
50 buff.getClass(), int.class, int.class);
51 defineClass.setAccessible(true);
52
53 // We directly call into ClassLoader.defineClass() to define the "Super" class. Also,
54 // rewrite its classfile so that it returns ___yyy___ instead of ___xxx___. Changing the
55 // classfile will guarantee that this class will NOT be loaded from the CDS archive.
56 Class cls = (Class)defineClass.invoke(loader, buff, new Integer(0), new Integer(buff.length));
57 System.out.println("Loaded : " + cls);
58
59 return cls;
60 }
61
62 /**
63 * @return the number of occurrences of the <code>from</code> string that
64 * have been replaced.
65 */
66 public static int replace(byte buff[], String from, String to) {
67 if (to.length() != from.length()) {
68 throw new RuntimeException("bad strings");
69 }
70 byte f[] = asciibytes(from);
71 byte t[] = asciibytes(to);
72 byte f0 = f[0];
73
74 int numReplaced = 0;
75 int max = buff.length - f.length;
76 for (int i=0; i<max; ) {
77 if (buff[i] == f0 && replace(buff, f, t, i)) {
78 i += f.length;
79 numReplaced ++;
80 } else {
129
130 if (fromString != null) {
131 replace(buff, fromString, toString);
132 }
133
134 //System.out.println("Loading from: " + ent + " (" + buff.length + " bytes)");
135
136 Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass",
137 buff.getClass(), int.class, int.class);
138 defineClass.setAccessible(true);
139 Class cls = (Class)defineClass.invoke(loader, buff, new Integer(0), new Integer(buff.length));
140
141 //System.out.println("Loaded : " + cls);
142 return cls;
143 }
144
145 public static byte[] getClassFileFromJar(File jarFile, String className) throws FileNotFoundException, IOException {
146 JarFile jf = new JarFile(jarFile);
147 JarEntry ent = jf.getJarEntry(className.replace('.', '/') + ".class");
148
149 DataInputStream dis = new DataInputStream(jf.getInputStream(ent));
150 byte[] buff = new byte[(int)ent.getSize()];
151 dis.readFully(buff);
152 dis.close();
153
154 return buff;
155 }
156 }
|
22 *
23 */
24
25 import java.io.*;
26 import java.lang.reflect.*;
27 import java.util.jar.*;
28
29 public class Util {
30 /**
31 * Invoke the loader.defineClass() class method to define the class stored in clsFile,
32 * with the following modification:
33 * <ul>
34 * <li> All ASCII strings in the class file bytes that matches fromString will be replaced with toString.
35 * NOTE: the two strings must be the exact same length.
36 * </ul>
37 */
38 public static Class defineModifiedClass(ClassLoader loader, File clsFile, String fromString, String toString)
39 throws FileNotFoundException, IOException, NoSuchMethodException, IllegalAccessException,
40 InvocationTargetException
41 {
42 try (DataInputStream dis = new DataInputStream(new FileInputStream(clsFile))) {
43 byte[] buff = new byte[(int)clsFile.length()];
44 dis.readFully(buff);
45 replace(buff, fromString, toString);
46
47 System.out.println("Loading from: " + clsFile + " (" + buff.length + " bytes)");
48
49 Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass",
50 buff.getClass(), int.class, int.class);
51 defineClass.setAccessible(true);
52
53 // We directly call into ClassLoader.defineClass() to define the "Super" class. Also,
54 // rewrite its classfile so that it returns ___yyy___ instead of ___xxx___. Changing the
55 // classfile will guarantee that this class will NOT be loaded from the CDS archive.
56 Class cls = (Class)defineClass.invoke(loader, buff, new Integer(0), new Integer(buff.length));
57 System.out.println("Loaded : " + cls);
58
59 return cls;
60 }
61 }
62
63 /**
64 * @return the number of occurrences of the <code>from</code> string that
65 * have been replaced.
66 */
67 public static int replace(byte buff[], String from, String to) {
68 if (to.length() != from.length()) {
69 throw new RuntimeException("bad strings");
70 }
71 byte f[] = asciibytes(from);
72 byte t[] = asciibytes(to);
73 byte f0 = f[0];
74
75 int numReplaced = 0;
76 int max = buff.length - f.length;
77 for (int i=0; i<max; ) {
78 if (buff[i] == f0 && replace(buff, f, t, i)) {
79 i += f.length;
80 numReplaced ++;
81 } else {
130
131 if (fromString != null) {
132 replace(buff, fromString, toString);
133 }
134
135 //System.out.println("Loading from: " + ent + " (" + buff.length + " bytes)");
136
137 Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass",
138 buff.getClass(), int.class, int.class);
139 defineClass.setAccessible(true);
140 Class cls = (Class)defineClass.invoke(loader, buff, new Integer(0), new Integer(buff.length));
141
142 //System.out.println("Loaded : " + cls);
143 return cls;
144 }
145
146 public static byte[] getClassFileFromJar(File jarFile, String className) throws FileNotFoundException, IOException {
147 JarFile jf = new JarFile(jarFile);
148 JarEntry ent = jf.getJarEntry(className.replace('.', '/') + ".class");
149
150 try (DataInputStream dis = new DataInputStream(jf.getInputStream(ent))) {
151 byte[] buff = new byte[(int)ent.getSize()];
152 dis.readFully(buff);
153 return buff;
154 }
155 }
156 }
|