1 |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
2 |
<html> |
3 |
<head> |
4 |
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> |
5 |
<meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type"> |
6 |
<meta content="en" http-equiv="Content-Language"> |
7 |
<title>ASM - ASM FAQ</title> |
8 |
<meta name="Description" content="ASM is a very small and very fast Java bytecode manipulation framework."> |
9 |
<meta name="Keywords" content="ASM,bytecode,manipulation,Java,open,source,free,software,BSD"> |
10 |
<meta name="Reply-to" content="webmaster@objectweb.org"> |
11 |
<meta name="Owner" content="ObjectWeb"> |
12 |
<meta name="Robots" content="index, follow"> |
13 |
<meta content="asm-team" name="author"> |
14 |
<meta content="asm-team@objectweb.org" name="email"> |
15 |
<script src="../js/objectweb.js" type="text/javascript"></script> |
16 |
<link type="text/css" href="../common.css" rel="stylesheet" id="stylesheet"> |
17 |
<link type="image/x-icon" href="../images/favicon.ico" rel="icon"> |
18 |
<link type="image/x-icon" href="../images/favicon.ico" rel="shortcut icon"> |
19 |
</head> |
20 |
<body marginheight="0" marginwidth="0" topmargin="0" leftmargin="0" onload="MM_preloadImages('../images/menu/boutonok2.gif','../images/menu/boutonsearch2.gif','../images/menu/boutonprint2.gif','../images/menu/boutonsubscribe2.gif')" bgcolor="#FFFFFF" class="bodyproject"> |
21 |
<table cellpadding="0" cellspacing="0" width="100%" border="0"> |
22 |
<tr> |
23 |
<td valign="top" width="245"><img alt=" " height="20" src="../images/pix.gif"></td><td width="100%" bgcolor="#E8EAF0" valign="bottom"> <a class="barre" href="http://consortium.objectweb.org/"> Consortium </a> <a class="barre" href="http://solutions.objectweb.org/"> Solutions </a> <a class="barre" href="http://middleware.objectweb.org/"> Middleware </a> <a class="barre" href="http://forge.objectweb.org/"> Forge </a> <a class="barre" href="http://myobjectweb.objectweb.org/"> MyObjectWeb </a></td> |
24 |
</tr> |
25 |
<tr> |
26 |
<td valign="top" width="245"><a href="http://www.objectweb.org/"><img alt="ObjectWeb Consortium" border="0" height="80" width="245" src="../images/logoow.gif"></a></td><td valign="top"> |
27 |
<table cellpadding="0" cellspacing="0" width="100%" border="0"> |
28 |
<tr> |
29 |
<td valign="top"><img alt=" " height="20" width="395" src="../images/pix.gif"></td><td valign="top" width="150"><img alt=" " height="20" width="150" src="../images/pix.gif"></td> |
30 |
</tr> |
31 |
<tr> |
32 |
<td valign="top"> |
33 |
<table cellpadding="5" cellspacing="0" border="0"> |
34 |
<tr> |
35 |
<td valign="top"></td><td valign="top"></td><td valign="top"></td><td valign="top"></td> |
36 |
</tr> |
37 |
</table> |
38 |
</td><td style="line-height: 20px;" valign="top" width="150"> |
39 |
<form action=""> |
40 |
<table> |
41 |
<tr> |
42 |
<td><select onChange="MM_goToURL('parent',this.options[this.selectedIndex].value);return document.MM_returnValue" name="navigation"><option>Go to ObjectWeb...</option><option value="http://www.objectweb.org/">Home Page</option><option value="http://consortium.objectweb.org/">Consortium</option><option value="http://solutions.objectweb.org/">Solutions</option><option value="http://middleware.objectweb.org/">Middleware</option><option value="http://forge.objectweb.org/">Project Forge</option><option value="http://myobjectweb.objectweb.org/">My ObjectWeb</option></select></td><td><input alt="Submit" border="0" onmouseover="MM_swapImage('ok','','../images/menu/boutonok2.gif',1)" onmouseout="MM_swapImgRestore()" src="../images/menu/boutonok1.gif" id="ok" name="Ok" type="image"></td> |
43 |
</tr> |
44 |
</table> |
45 |
</form> |
46 |
<form target="_blank" action="http://www.google.com/custom" method="get"> |
47 |
<input value="S:http://www.objectweb.org/;GL:0;AH:center;LH:81;L:http://www.objectweb.org/media/owlogos/ObjectWeb-small.gif;LW:236;AWFID:48faba182d01f379;" name="cof" type="hidden"><input value="objectweb.org;mail-archive.objectweb.org;www.enhydra.org" name="domains" type="hidden"><input value="objectweb.org;www.enhydra.org" name="sitesearch" type="hidden"> |
48 |
<table rowspan="0" colspan="0"> |
49 |
<tr> |
50 |
<td><input onblur="if (this.value=='') this.value='search'" onfocus="this.value=''" value="" maxlength="255" size="10" name="q" type="text"></td><td><input alt="Submit" onmouseover="MM_swapImage('search','','../images/menu/boutonsearch2.gif',1)" onmouseout="MM_swapImgRestore()" src="../images/menu/boutonsearch1.gif" id="search" name="sa" type="image"></td><td><a alt="Submit" onmouseover="MM_swapImage('print','','../images/menu/boutonprint2.gif',1)" onmouseout="MM_swapImgRestore()" target="_blank" href="faq_print.html"><img id="print" border="0" height="20" width="20" name="print" alt="Print" src="../images/menu/boutonprint1.gif"></a></td> |
51 |
</tr> |
52 |
</table> |
53 |
<p class="glose"> |
54 |
<strong><a target="_blank" class="lienglose" href="http://www.objectweb.org/search.html">Advanced</a></strong> - Powered by Google</p> |
55 |
</form> |
56 |
</td> |
57 |
</tr> |
58 |
</table> |
59 |
</td> |
60 |
</tr> |
61 |
</table> |
62 |
<table cellpadding="0" cellspacing="0" border="0" width="100%" summary=""> |
63 |
<tr> |
64 |
<td valign="top" width="20"><img alt=" " height="1" width="20" src="../images/pix.gif"></td><td valign="top" width="160"><img alt=" " height="1" width="160" src="../images/pix.gif"><br> |
65 |
<br> |
66 |
<br> |
67 |
<br> |
68 |
<br> |
69 |
<p style="font-size: 16px; font-weight: bold; color: #433C7B;">ASM</p> |
70 |
<p> |
71 |
<span class="menutitre">Project Links</span> |
72 |
<br> |
73 |
· <a class="menu" target="_self" href="../index.html">Home</a> |
74 |
<br> |
75 |
· <a class="menu" target="_self" href="../download/index.html">Download</a> |
76 |
<br> |
77 |
· <a class="menu" target="_self" href="../eclipse/index.html">Eclipse plugins</a> |
78 |
<br> |
79 |
· <a class="menu" target="_self" href="http://www.objectweb.org/wws/lists/projects/asm">Mailing Lists</a> |
80 |
<br> |
81 |
· <a class="menu" target="_self" href="../license.html">License</a> |
82 |
<br> |
83 |
· <a class="menu" target="_self" href="../history.html">History</a> |
84 |
<br> |
85 |
</p> |
86 |
<p> |
87 |
<span class="menutitre">Developers' Corner</span> |
88 |
<br> |
89 |
· <a class="menu" target="_self" href="http://forge.objectweb.org/cvs/?group_id=23">CVS Repository</a> |
90 |
<br> |
91 |
· <a class="menu" target="_self" href="http://forge.objectweb.org/projects/asm/">ObjectWeb Forge Site</a> |
92 |
<br> |
93 |
</p> |
94 |
<p> |
95 |
<span class="menutitre">About</span> |
96 |
<br> |
97 |
· <a class="menu" target="_self" href="../users.html">Users</a> |
98 |
<br> |
99 |
· <a class="menu" target="_self" href="../team.html">Team</a> |
100 |
<br> |
101 |
· <a class="menu" target="_self" href="mailto:asm-team@objectweb.org">Contacts</a> |
102 |
<br> |
103 |
</p> |
104 |
</td><td align="left" width="100%" valign="top"> |
105 |
<h1>Frequently Asked Questions</h1> |
106 |
|
107 |
<p>Here are some frequently asked questions about ASM, gathered by |
108 |
<a href="mailto:m.proctor@bigfoot.com">Mark Proctor</a>.</p> |
109 |
|
110 |
<ul> |
111 |
|
112 |
<li> |
113 |
<a href="#Q0">0. How do I start using ASM?</a> |
114 |
</li> |
115 |
|
116 |
<li> |
117 |
<a href="#Q1">1. How do I remove a method/field?</a> |
118 |
</li> |
119 |
|
120 |
<li> |
121 |
<a href="#Q2">2. How do I replace a method/field? I end up with duplicated members!</a> |
122 |
</li> |
123 |
|
124 |
<li> |
125 |
<a href="#Q3">3. How do I make ASM calculate visitMaxs for me?</a> |
126 |
</li> |
127 |
|
128 |
<li> |
129 |
<a href="#Q4">4. Why do I get the [xxx] verifier error?"</a> |
130 |
</li> |
131 |
|
132 |
<li> |
133 |
<a href="#Q5">5. How do I add my bytecode class to the system class loader?</a> |
134 |
</li> |
135 |
|
136 |
<li> |
137 |
<a href="#Q6">6. How do I rename my class?</a> |
138 |
</li> |
139 |
|
140 |
<li> |
141 |
<a href="#Q7">7. How do method descriptors work?</a> |
142 |
</li> |
143 |
|
144 |
<li> |
145 |
<a href="#Q8">8. How can ASM help me create my descriptor types?</a> |
146 |
</li> |
147 |
|
148 |
<li> |
149 |
<a href="#Q9">9. How do I generate Setters and Getters for my class?</a> |
150 |
</li> |
151 |
|
152 |
<li> |
153 |
<a href="#Q10">10. How do I get the bytecode of an existing class?</a> |
154 |
</li> |
155 |
|
156 |
<li> |
157 |
<a href="#Q11">11. How do I generate [some Java code] with ASM?</a> |
158 |
</li> |
159 |
|
160 |
<li> |
161 |
<a href="#Q12">12. How does the [xxx] bytecode instruction work?</a> |
162 |
</li> |
163 |
|
164 |
<li> |
165 |
<a href="#Q13">13. Is ASM thread safe?</a> |
166 |
</li> |
167 |
|
168 |
<li> |
169 |
<a href="#Q14">14. What is the earliest JDK required to use ASM?</a> |
170 |
</li> |
171 |
|
172 |
</ul> |
173 |
|
174 |
|
175 |
<h3> |
176 |
<a name="Q0"></a>0. How do I start using ASM?</h3> |
177 |
|
178 |
|
179 |
<p>If you want to use ASM to generate classes from scratch, write a Java source |
180 |
file that is representative of the classes you want to generate, compile it(*), and |
181 |
then run the <a href="#Q10">ASMifier</a> on the compiled class to see the Java source code that |
182 |
generates this class with ASM. If you are using Eclipse it is even easier, |
183 |
thanks to the <a href="../eclipse.html">Bytecode Outline</a> plugin.</p> |
184 |
|
185 |
|
186 |
<p>If you want to use ASM to transform classes, write two Java source files - |
187 |
first with and second without features that has to be added or removed and try |
188 |
to keep other differences as minimal as you can, compile them(*), and then run the |
189 |
<a href="#Q10">ASMifier</a> on both of them. Then compare the results with some visual diff tool. |
190 |
If you are using Eclipse it is even easier, thanks to the compare tool of the |
191 |
<a href="../eclipse.html">Bytecode Outline</a> plugin.</p> |
192 |
|
193 |
|
194 |
<p>(*) Note that javac may produce different code for different -target, |
195 |
so you'll have to compile for your target environment, repeat that |
196 |
excercise for all required target's or use the earliest bytecode version |
197 |
if possible.</p> |
198 |
|
199 |
|
200 |
<h3> |
201 |
<a name="Q1"></a>1. How do I remove a method/field?</h3> |
202 |
|
203 |
|
204 |
<p>Use the ClassAdapter and return nothing:</p> |
205 |
|
206 |
<pre> public FieldVisitor visitField (String name, ...) { |
207 |
if (removeField(name)) { |
208 |
// do nothing, in order to remove this field |
209 |
return null; |
210 |
} else { |
211 |
// make the next visitor visit this field, in order to keep it |
212 |
return super.visitField(name, ...); |
213 |
} |
214 |
}</pre> |
215 |
|
216 |
|
217 |
<h3> |
218 |
<a name="Q2"></a>2. How do I replace a method/field? I end up with duplicated members!</h3> |
219 |
|
220 |
|
221 |
<p>You must either return the replacement method/field when you visit the original one using the |
222 |
ClassAdapter, or you must first remove the original method/field in the ClassAdapter (see |
223 |
<a href="#Q1">"1. How do I remove a method/field?"</a>), and then add the new method/field |
224 |
by calling a visit method on the ClassWriter.</p> |
225 |
|
226 |
|
227 |
<h3> |
228 |
<a name="Q3"></a>3. How do I make ASM calculate visitMaxs for me?</h3> |
229 |
|
230 |
|
231 |
<p>When calling the constructor for ClassWriter pass true. You must also |
232 |
still include the visitMaxs instruction, but the values you give are |
233 |
ignored, so visitMaxs(0,0) is fine.</p> |
234 |
|
235 |
|
236 |
<h3> |
237 |
<a name="Q4"></a>4. Why do I get the [xxx] verifier error?</h3> |
238 |
|
239 |
|
240 |
<p>If the message given by the JVM class verifier does not help you, you can |
241 |
use the verifier provided by ASM. For example, if you use a wrong constant when |
242 |
making "return" on a method, or if you do not use the appropriate LOAD or STORE |
243 |
instruction, depending on the local variable type, the JVM class verifier gives |
244 |
a "Register x contains wrong type" or "Expecting to find x on stack" error which |
245 |
does not say anything about the instruction that caused the error. In this case |
246 |
you can use the class verifier provided by ASM:</p> |
247 |
|
248 |
|
249 |
<p> |
250 |
<code>java -cp "asm.jar;asm-tree.jar;asm-analysis.jar;asm-util.jar" |
251 |
org.objectweb.asm.util.CheckClassAdapter org/domain/package/YourClass.class</code> |
252 |
</p> |
253 |
|
254 |
|
255 |
<p>For example, in the helloworld example in the ASM distribution, if you replace |
256 |
visitLdc("Hello world!") with visitLdc(new Integer(1234)) you get the following |
257 |
error message when the generated class is verified as above:</p> |
258 |
|
259 |
|
260 |
<pre>org.objectweb.asm.tree.analysis.AnalyzerException: Error at instruction 2: Argument 1: expected Ljava/lang/String;, but found I |
261 |
at org.objectweb.asm.tree.analysis.Analyzer.analyze(Unknown Source) |
262 |
at org.objectweb.asm.util.CheckClassAdapter.main(Unknown Source) |
263 |
main([Ljava/lang/String;)V |
264 |
00000 [Ljava/lang/String;. : GETSTATIC java/lang/System out Ljava/io/PrintStream; |
265 |
00001 [Ljava/lang/String;. Ljava/io/PrintStream; : LDC 1234 |
266 |
00002 [Ljava/lang/String;. Ljava/io/PrintStream;I : INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V |
267 |
00003 null : RETURN</pre> |
268 |
|
269 |
|
270 |
<p>This shows that the error comes from instruction 2 in method main. The instruction list |
271 |
shows that this instruction is INVOKEVIRTUAL. It also shows the types of the local variables |
272 |
and of the operand stack values just before this instruction will be executed (here local |
273 |
variable 0 contains a String, local variable 1 is not initialized, and the stack contains |
274 |
a PrintStream and an int). As explained in the error message, the println method called by |
275 |
INVOKEVIRTUAL expects a String as first argument, but the stack value corresponding to this |
276 |
argument is an int. Then either the INVOKEVIRTUAL instruction is wrong, or the instruction |
277 |
that pushed the integer is wrong.</p> |
278 |
|
279 |
|
280 |
<p>If your class is so "corrupted" that you cannot read it with a ClassReader, |
281 |
try to generate it by using a CheckClassAdapter in front of a ClassWriter:</p> |
282 |
|
283 |
<pre> ClassWriter cv = new ClassWriter(true); |
284 |
cv = new CheckClassAdapter(cv); |
285 |
// generate your class here: |
286 |
cv.visit(...); |
287 |
...</pre> |
288 |
|
289 |
<p>You will probably get an exception which will indicate why your generated class |
290 |
is incorrect. For example, if you forget to call visit(...) (which can happen if you |
291 |
forget to call super.visit(...) in a class adapter), the generated class |
292 |
contains an invalid constant pool index, and ClassReader is unable to read it. If |
293 |
you generate your class by using a CheckClassAdapter, as above, you get an |
294 |
exception "Cannot visit member before visit has been called.", which shows that |
295 |
you forgot to call the visit method.</p> |
296 |
|
297 |
|
298 |
<h3> |
299 |
<a name="Q5"></a>5. How do I add my bytecode class to the system class loader?</h3> |
300 |
|
301 |
|
302 |
<p>You must first have the security to do this, as defined in the policy |
303 |
file - there are no security restrictions as default for a standard java |
304 |
install. Use ClassLoader.defineClass, this however is a "protected" method, so |
305 |
you must use reflection to gain access to it:</p> |
306 |
|
307 |
<pre> private Class loadClass (byte[] b) { |
308 |
//override classDefine (as it is protected) and define the class. |
309 |
Class clazz = null; |
310 |
try { |
311 |
ClassLoader loader = ClassLoader.getSystemClassLoader(); |
312 |
Class cls = Class.forName("java.lang.ClassLoader"); |
313 |
java.lang.reflect.Method method = |
314 |
cls.getDeclaredMethod("defineClass", new Class[] { String.class, byte[].class, int.class, int.class }); |
315 |
|
316 |
// protected method invocaton |
317 |
method.setAccessible(true); |
318 |
try { |
319 |
Object[] args = new Object[] { className, b, new Integer(0), new Integer(b.length)}; |
320 |
clazz = (Class) method.invoke(loader, args); |
321 |
} finally { |
322 |
method.setAccessible(false); |
323 |
} |
324 |
} catch (Exception e) { |
325 |
e.printStackTrace(); |
326 |
System.exit(1); |
327 |
} |
328 |
return clazz; |
329 |
}</pre> |
330 |
|
331 |
<p>Alternatively you can create your own ClassLoader by extending the |
332 |
existing class loader (example needed here).</p> |
333 |
|
334 |
|
335 |
|
336 |
<h3> |
337 |
<a name="Q6"></a>6. How do I rename my class?</h3> |
338 |
|
339 |
|
340 |
<p>It is not enough to rename just the class, you must also rename all the |
341 |
references to class members using the MethodAdapter.</p> |
342 |
|
343 |
<pre>class ClassRenamer extends ClassAdapter implements Opcodes { |
344 |
|
345 |
private Set oldNames; |
346 |
private final String newName; |
347 |
|
348 |
public ClassRenamer(ClassVisitor cv, Set oldNames, String newName) { |
349 |
super(cv); |
350 |
this.oldNames = oldNames; |
351 |
this.newName = newName; |
352 |
} |
353 |
|
354 |
public void visit (int version, int access, String name, String signature, String superName, String[] interfaces) { |
355 |
oldNames.add(name); |
356 |
cv.visit(version, ACC_PUBLIC, newName, signature, superName, interfaces); |
357 |
} |
358 |
|
359 |
public MethodVisitor visitMethod (int access, String name, String desc, String signature, String[] exceptions) { |
360 |
MethodVisitor mv = cv.visitMethod(access, name, fixDesc(desc), fix(signature), exceptions); |
361 |
if (mv != null && (access & ACC_ABSTRACT) == 0) { |
362 |
mv = new MethodRenamer(mv); |
363 |
} |
364 |
return mv; |
365 |
} |
366 |
|
367 |
class MethodRenamer extends MethodAdapter { |
368 |
|
369 |
public MethodRenamer (final MethodVisitor mv) { |
370 |
super(mv); |
371 |
} |
372 |
|
373 |
public void visitTypeInsn (int i, String s) { |
374 |
if (oldNames.contains(s)) { |
375 |
s = newName; |
376 |
} |
377 |
mv.visitTypeInsn(i, s); |
378 |
} |
379 |
|
380 |
public void visitFieldInsn (int opcode, String owner, String name, String desc) { |
381 |
if (oldNames.contains(owner)) { |
382 |
mv.visitFieldInsn(opcode, newName, name, fix(desc)); |
383 |
} else { |
384 |
mv.visitFieldInsn(opcode, owner, name, fix(desc)); |
385 |
} |
386 |
} |
387 |
|
388 |
public void visitMethodInsn (int opcode, String owner, String name, String desc) { |
389 |
if (oldNames.contains(owner)) { |
390 |
mv.visitMethodInsn(opcode, newName, name, fix(desc)); |
391 |
} else { |
392 |
mv.visitMethodInsn(opcode, owner, name, fix(desc)); |
393 |
} |
394 |
} |
395 |
} |
396 |
|
397 |
private String fix (String s) { |
398 |
if (s != null) { |
399 |
Iterator it = oldNames.iterator(); |
400 |
String name; |
401 |
while (it.hasNext()) { |
402 |
name = (String) it.next(); |
403 |
if (s.indexOf(name) != -1) { |
404 |
s = desc.replaceAll(name, newName); |
405 |
} |
406 |
} |
407 |
} |
408 |
return s; |
409 |
} |
410 |
}</pre> |
411 |
|
412 |
|
413 |
|
414 |
<h3> |
415 |
<a name="Q7"></a>7. How do method descriptors work?</h3> |
416 |
|
417 |
|
418 |
<p>To understand this best it's good to read the source code of Type.java. |
419 |
Here is a quick overview:</p> |
420 |
|
421 |
<ul> |
422 |
|
423 |
<li>Primitive representations: |
424 |
<ul> |
425 |
|
426 |
<li>'V' - void</li> |
427 |
|
428 |
<li>'Z' - boolean</li> |
429 |
|
430 |
<li>'C' - char</li> |
431 |
|
432 |
<li>'B' - byte</li> |
433 |
|
434 |
<li>'S' - short</li> |
435 |
|
436 |
<li>'I' - int</li> |
437 |
|
438 |
<li>'F' - float</li> |
439 |
|
440 |
<li>'J' - long</li> |
441 |
|
442 |
<li>'D' - double</li> |
443 |
|
444 |
</ul> |
445 |
|
446 |
</li> |
447 |
|
448 |
<li>Class representations: |
449 |
<ul> |
450 |
|
451 |
<li>L<class>;</li> |
452 |
|
453 |
<li>Ljava/io/ObjectOutput;</li> |
454 |
|
455 |
<li>Ljava/lang/String;</li> |
456 |
|
457 |
</ul> |
458 |
|
459 |
</li> |
460 |
|
461 |
</ul> |
462 |
|
463 |
<p>Examples:</p> |
464 |
|
465 |
<ul> |
466 |
|
467 |
<li>public void method() |
468 |
<ul> |
469 |
<li> |
470 |
<code>cw.visitMethod(ACC_PUBLIC, methodName, "()V", null, null);</code> |
471 |
</li> |
472 |
</ul> |
473 |
</li> |
474 |
|
475 |
<li>public void method(String s, int i) |
476 |
<ul> |
477 |
<li> |
478 |
<code>cw.visitMethod(ACC_PUBLIC, methodName, "(Ljava/lang/String;I)V", null, null);</code> |
479 |
</li> |
480 |
</ul> |
481 |
</li> |
482 |
|
483 |
<li>public String method(String s, int i, boolan flag) |
484 |
<ul> |
485 |
<li> |
486 |
<code>cw.visitMethod(ACC_PUBLIC, methodName, "(Ljava/lang/String;IZ)Ljava/lang/String;", null, null);</code> |
487 |
</li> |
488 |
</ul> |
489 |
</li> |
490 |
|
491 |
</ul> |
492 |
|
493 |
|
494 |
|
495 |
<h3> |
496 |
<a name="Q8"></a>8. How can ASM help me create my descriptor types?</h3> |
497 |
|
498 |
|
499 |
<p>Types.java provides the static method Type.getDescriptor, which takes a |
500 |
Class as a parameter.</p> |
501 |
|
502 |
<p>Examples:</p> |
503 |
<ul> |
504 |
|
505 |
<li> |
506 |
<code>String desc = Type.getDescriptor(String.class);</code> |
507 |
</li> |
508 |
|
509 |
<li> |
510 |
<code>String desc = Type.getDescriptor(int.class);</code> |
511 |
</li> |
512 |
|
513 |
<li> |
514 |
<code>String desc = Type.getDescriptor(java.io.ObjectOutput.class);</code> |
515 |
</li> |
516 |
|
517 |
</ul> |
518 |
|
519 |
|
520 |
|
521 |
<h3> |
522 |
<a name="Q9"></a>9. How do I generate Setters and Getters for my class?</h3> |
523 |
|
524 |
|
525 |
<p>Use the following code (this assumes that visitMaxs are computed by ASM - see |
526 |
<a href="#Q3">"3. How do I make ASM calculate visitMaxs for me?"</a>):</p> |
527 |
|
528 |
<pre>void createSetter (String propertyName, String type, Class c) { |
529 |
String methodName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1); |
530 |
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, methodName, "(" + type + ")V", null, null); |
531 |
mv.visitVarInsn(ALOAD, 0); |
532 |
mv.visitVarInsn(Type.getType(c).getOpcode(ILOAD, 1)); |
533 |
mv.visitFieldInsn(PUTFIELD, className, propertyName, type); |
534 |
mv.visitInsn(RETURN); |
535 |
mv.visitMaxs(0, 0); |
536 |
} |
537 |
|
538 |
void createGetter (String propertyName, String returnType, Class c) { |
539 |
String methodName = "get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1); |
540 |
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, methodName, "()" + returnType, null, null); |
541 |
mv.visitVarInsn(ALOAD, 0); |
542 |
mv.visitFieldInsn(GETFIELD, internalClassName, propertyName, returnType); |
543 |
mv.visitInsn(Type.getType(c).getOpcode(IRETURN)); |
544 |
mv.visitMaxs(0, 0); |
545 |
}</pre> |
546 |
|
547 |
|
548 |
|
549 |
<h3> |
550 |
<a name="Q10"></a>10. How do I get the bytecode of an existing class?</h3> |
551 |
|
552 |
|
553 |
<p>If you want the bytecode instructions themselves, use TraceClassVisitor. If you |
554 |
want the ASM code to generate these bytecode instructions, use ASMifierClassVisitor. |
555 |
Both classes provide a "main" method to allow them to be |
556 |
called from the command line, passing your fully qualified class name as a |
557 |
parameter. |
558 |
Example:</p> |
559 |
|
560 |
<p> |
561 |
<code>java -classpath "asm.jar;asm-util.jar;yourjar.jar" |
562 |
org.objectweb.asm.util.ASMifierClassVisitor org.domain.package.YourClass</code> |
563 |
</p> |
564 |
|
565 |
<p>or</p> |
566 |
|
567 |
<p> |
568 |
<code>java -classpath "asm.jar;asm-util.jar" |
569 |
org.objectweb.asm.util.ASMifierClassVisitor org/domain/package/YourClass.class</code> |
570 |
</p> |
571 |
|
572 |
<p>Another, much easier method, if you are using Eclipse, is to use the |
573 |
<a href="../eclipse.html">Bytecode Outline</a> plugin.</p> |
574 |
|
575 |
|
576 |
<h3> |
577 |
<a name="Q11"></a>11. How do I generate [some Java code] with ASM?</h3> |
578 |
|
579 |
|
580 |
<p>If you want to know how to generate a synchronized block, a try catch |
581 |
block, a finally statement, or any other Java construct, write the Java code |
582 |
you want to generate in a temporary class, compile it with javac, and then |
583 |
use the ASMifierClassVisitor to get the ASM code that will generate this class (see |
584 |
<a href="#Q10">"10. How do I get the bytecode of an existing class?"</a>). |
585 |
</p> |
586 |
|
587 |
|
588 |
|
589 |
<h3> |
590 |
<a name="Q12"></a>12. How does the [xxx] bytecode instruction work?</h3> |
591 |
|
592 |
|
593 |
<p>See <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions.doc.html">chapter |
594 |
6</a> of the Java Virtual Machine Specification. |
595 |
</p> |
596 |
|
597 |
|
598 |
|
599 |
<h3> |
600 |
<a name="Q13"></a>13. Is ASM thread safe?</h3> |
601 |
|
602 |
|
603 |
<p>The Type and ClassReader classes are thread safe, i.e. several threads can |
604 |
use a single Type object or a single ClassReader object concurrently without |
605 |
problems. The ClassWriter and MethodWriter classes are <em>not</em> thread safe, |
606 |
i.e. a single class cannot be generated by several concurrent threads (but, |
607 |
of course, several threads can generate distinct classes concurrently, if each |
608 |
thread uses its own ClassWriter instance). In order to generate a single class |
609 |
by using several concurrent threads, one should use ClassAdapter and |
610 |
MethodAdapter instances that delegate to normal ClassWriter and MethodWriter |
611 |
instances, and whose methods are all synchronized.</p> |
612 |
|
613 |
<p>More generally, ClassVisitor and MethodVisitor implementations, such as |
614 |
ClassWriter and ClassAdapter, do not have to be thread safe. However, non thread |
615 |
safe visitors can be made thread safe just by using a synchronizing class |
616 |
adapter in front of them.</p> |
617 |
|
618 |
|
619 |
|
620 |
<h3> |
621 |
<a name="Q14"></a>14. What is the earliest JDK required to use ASM?</h3> |
622 |
|
623 |
|
624 |
<p>The org.objectweb.asm package should work with JDK 1.1, or even with JDK 1.0 |
625 |
if Type is not used. Indeed, this package only requires the following JDK classes |
626 |
and methods:</p> |
627 |
|
628 |
<ul> |
629 |
|
630 |
<li>in java.io: InputStream, IOException (only in two constructors of |
631 |
ClassReader)</li> |
632 |
|
633 |
<li>in java.lang.reflect: Method (only in Type)</li> |
634 |
|
635 |
<li>in java.lang: |
636 |
<ul> |
637 |
|
638 |
<li>Object, String, StringBuffer</li> |
639 |
|
640 |
<li>Long, Double, Float, Void, Byte, Boolean ...</li> |
641 |
|
642 |
<li>System.arraycopy</li> |
643 |
|
644 |
<li>ClassLoader.getSystemClassLoader, |
645 |
ClassLoader.getSystemResourceAsStream (only in one constructor of |
646 |
ClassReader)</li> |
647 |
|
648 |
</ul> |
649 |
|
650 |
</li> |
651 |
|
652 |
</ul> |
653 |
|
654 |
<p>The asm.util and asm.tree packages require JDK 1.2, since they use the |
655 |
List interface and the ArrayList class. |
656 |
</p> |
657 |
|
658 |
|
659 |
|
660 |
</td><td valign="top" width="10"><img alt=" " height="1" width="10" src="../images/pix.gif"></td> |
661 |
</tr> |
662 |
<tr> |
663 |
<td valign="top" width="20"><img alt=" " height="1" width="20" src="../images/pix.gif"></td><td valign="top" width="160"><img alt=" " height="1" width="160" src="../images/pix.gif"></td><td valign="top"><img alt=" " height="1" width="465" src="../images/pix.gif"><br> |
664 |
<address>Copyright © 1999-2005, <a href="http://www.objectweb.org/">ObjectWeb Consortium</a> | <a href="http://consortium.objectweb.org/contact.html">contact</a> | <a href="mailto:webmaster@objectweb.org">webmaster</a> | Last modified at 2005-02-22 05:27 PM</address> |
665 |
</td><td valign="top" width="10"><img alt=" " height="1" width="10" src="../images/pix.gif"></td> |
666 |
</tr> |
667 |
</table> |
668 |
<br> |
669 |
</body> |
670 |
</html> |