Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I must say that this is quite an interesting question you have here. I'm sorry if my answer is a bit long but I've tried to give you as much (what I think is) useful information as I could, in order to try to help you and others that land in this question.</p> <h2>Question 1</h2> <blockquote> <p>Is the following correct: I cannot ruse the javassist CtMethod.instrument() or CtMethod.insertAt() methods because those methods expect a string containing a valid Java expression and I cannot write an invokedynamic in Java syntax?</p> </blockquote> <p>You are correct. </p> <p><strong>CtMethod.insertAt()</strong> can only works with Java code not bytecode opcodes. <strong>CtMethod.instrument()</strong>, on the other hand, allows you to handle bytecode and even modify it in a very limited way with <a href="http://www.csg.is.titech.ac.jp/~chiba/javassist/html/javassist/expr/ExprEditor.html" rel="nofollow">ExprEditor</a> and <a href="http://www.csg.is.titech.ac.jp/~chiba/javassist/html/javassist/CodeConverter.html" rel="nofollow">CodeConverter</a>. But as I said, it's very limited what they allow you to change, and for what you are trying to achieve both modifiers cannot help you.</p> <h2>Question 2</h2> <blockquote> <p>The parameters to an invokestatic are handled just like the parameters of an invokevirtual or invokestatic, right? What I mean is, you put the parameters onto the stack before the invokedynamic just like you would do it for a invokevirtual?</p> </blockquote> <p>I don't know if I fully understood what you really are asking here (you repeated invokestatic in your 1st sentence). I think what you are asking - and correct me if I'm wrong - is, if parameters in <em>invokedynamic</em> are handled the same way as they are in <em>invokevirtual</em> and <em>invokestatic</em>. Making you able to simply switch <em>invokevirtual</em> and <em>invokestatic</em> for an <em>invokedynamic</em>. I'll assume it is while answering this question... </p> <p>First thing you have to be careful is that <em>invokevirtual</em> and <em>invokestatic</em> are themselves different when handling the stack. <em>Invokevirtual</em> besides pushing into the stack the arguments needed, as <em>invokestatic</em> does, it also pushes the object reference so the method call can be linked.</p> <hr> <p><strong>SideNote</strong></p> <p>You probably already know this, but I'm adding this additional information just in case someone else lands in this question and is wondering why <em>invokestatic</em> and <em>invokevirtual</em> handle differently the stack.</p> <ul> <li><p><em>invokestatic</em> opcode is used to invoke static methods in a class, this means that at compile time the JVM knows exactly how to do the method call linking.</p></li> <li><p>On the other hand, <em>invokedynamic</em> opcode is used when there's a method call to an object instance. Since when compiling there's no way to know where to link the method call to, it can only be linked at runtime when the JVM knows the correct object reference. </p></li> </ul> <hr> <p>My advice when having doubts in how the opcodes works is to check the chapter regarding <a href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html" rel="nofollow">JVM instruction set</a> in the <a href="http://docs.oracle.com/javase/specs/jvms/se7/html/" rel="nofollow">JVM specification</a> (links are for JVM 7, the current version when writing this).</p> <p>I've just done that to check the 3 opcodes we're talking here.</p> <p>Both opcodes, <a href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.invokestatic" rel="nofollow">invokestatic</a> and <a href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.invokedynamic" rel="nofollow">invokedynamic</a>, have the same operand stack definition:</p> <pre><code>..., [arg1, [arg2 ...]] → ... </code></pre> <p>As I had said previously <a href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.invokevirtual" rel="nofollow">invokevirtual</a> has a different operand stack definition, which is:</p> <pre><code>..., objectref, [arg1, [arg2 ...]] → ... </code></pre> <p>My first assumption here (and I must warn you I didn't yet dive that much into the <em>invokedynamic</em> opcode) is that you can't change the <em>invokevirtual</em> for an <em>invokedynamic</em> in such a simple way as you do it with <em>invokestatic</em>. I'm saying this because <em>invokedynamic</em> is not expecting any object reference in the stack.</p> <p>My advice for reaching a better understanding of this case would be to code an example in Java, using the <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/invoke/package-summary.html" rel="nofollow">java.lang.invoke</a> package, which will allow you to create java bytecode that uses <em>invokedynamic</em> opcode. And after compiling the classes, inspecting the generated bytecode using the command <code>javap -l -c -v -p</code>.</p> <h2>Question 3</h2> <blockquote> <p>Is there example code (or could you come up with some) that uses Javassist to create an invokedynamic bytecode?</p> </blockquote> <p>Not that I'm aware of. I've also googled a bit (as you probably already did too) and I haven't found anything. I think you're post will give the first code example for javassist :)</p> <h2>Some more notes</h2> <blockquote> <p>So essentially you have to manage the whole constant pool entries yourself. Which is OK but I am concerned that I don't get it right and introduce weird issues later</p> </blockquote> <p>As long as you use the <a href="http://www.csg.is.titech.ac.jp/~chiba/javassist/html/javassist/bytecode/ConstPool.html" rel="nofollow">ConstPool</a> class to manage your constant pool, javassist will handle everything for you without creating problems.</p> <p>Besides, if you create a corrupted contant pool, most often (most probably always) what will happen is that you'll have a ClassFormatException error as soon as you try to load the class or invoke a modified method. I would say this is one of those cases where it either works or not.</p> <p>I can't think of a scenario where some sort of weird bug could be hidden waiting for that nasty moment to haunt you when you less expect (notice that I said I can't think of, doesn't really mean they don't exist). I would even risk to say that it's fairly safe to say that as long as you can load the class and call it's methods without having the JVM crashing you'll be ok.</p> <blockquote> <p>Is there an easier way to do this (a helper method or so)?</p> </blockquote> <p>I don't think so. Javassist helps you a lot in bytecode modification but it's when you're working with the higher level API (as in, writing java code and injecting that code or moving/copying CtMethods,Ctclasses, ect). When you use the low level API where you have to handle all the bytecode, you're pretty much on your own.</p> <p>I know it's probably not a spot on answer as you were looking for, but I hope I've shed some light over the subject.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload