It is possible to set the method body using CtMethod.setBody(".."), but I do not find any API to get the method body in string format.
This is not possible.
Javassist is not a decompiler. A method in a class file is represented in Java byte code. Javassist knows how to translate Java source code to byte code but not the other way round. Also, Java byte code might not even be expressable as Java source code, for example when written in a non-Java JVM language.
Related
I'm currently trying to learn how to create Kotlin Compiler Plugins for the JVM and I'd like to change a method's body as an example, the API requires to manipulate Java byte code using ASM API in order to make any changes to a class' components. The Kotlin compiler plugin provides this class where, if for example, you'd like to modify a class' method body, you'd need to override the newMethod function, which returns a MethodVisitor instance, which is the one that you'd need to manually modify using the ASM's API.
I would like to be able of doing so without having to write ASM instructions and I was wondering if there was a way to add instructions straight into a MethodVisitor object using Byte Buddy's high level API?
Many thanks!
Quite honestly, the API is a bit awkward since it does not follow the standard model of ASM where you wrap a class visitor and since it shades the ASM dependency which makes it non-compatible with any ASM user.
In Byte Buddy, you can register your own visitors so what you can do is to define a custom class in Byte Buddy, and before calling make, you'd register an AsmVisitorWrapper which delegates to the visitor Kotlin yields. You'd need to proxy all method calls from Kotlin's ASM namespace to Byte Buddy's ASM namespace, though what you can do using method handles.
I am new to swift. I am trying to find a way to accomplish that.
In objective-c project, when I NSLog a response body from api, I got something like this. its pretty and readable. Ojective-c Debug area
However, when i use swift, when I print a response body from api, I got something like that. It's super hard to read. Swift Debug area
is there any way in swift, i could see the same format in debug area same as objective-c project.
If anyone could help, I really appreciate.
Thanks in advance.
It mainly depends on what you're trying to print in the Debug area. From Apple docs:
Swift provides a default debugging textual representation for any type. That default representation is used by the String(reflecting:) initializer and the debugPrint(_:) function for types that don’t provide their own.
From the image you've linked, it looks like you're printing a Dictionary, which prints out like that and there's not a straightforward way to change it. Considering you're getting data from an API, you can do debugging in three ways:
Print the raw body: if your server is returning JSON, that's usually readable and, in case it isn't, there are many JSON formatters/viewers online.
Parse the response into instances of a class that you define as conforming to CustomDebugStringConvertible; then, print the resulting array. This will not work in case the server response is malformed.
Loop through the dictionary and manually print keys and values in a format that looks readable to you.
I am using a QWebView and call to setHtml() to display some HTML/JavaScript pages. I am passing data updates using QWebFrame::evaluateJavaScript by passing it a QString containing a call to a JavaScript function (with arguments). After reading about the Qt WebKit Bridge I
feel like there should be a better way to do his. I see discussion of exposing Qt objects / functions in C++ to the JavaScript, but not the other direction. (I do not want the JavaScript to poll the C++ side for updates.) Is there a way to connect a JavaScript function as a slot to a Qt/C++ signal? (Or a similar pattern) I feel like I have looked through a lot of docs, posted questions (even the 'Similar Questions' as I type this), but have not seen examples of this. Appreciate any info, links or nudges in the right direction.
Use addToJavaScriptWindow object for exposing your C++ objects the Javascript tier:
page()->mainFrame()->addToJavaScriptWindowObject(QString("myObject"), myObject);
Check documentation here:
http://qt-project.org/doc/qt-4.8/qwebframe.html#addToJavaScriptWindowObject
That will expose your C++ myObject as "myObject".
Then, you can do exactly what you are looking for on your post, let's suppose myObject declares a signal in the following way:
signal:
mySignal(QString aParameter);
you can simply connect that signal to a slot on your web side as follows:
myObject.mySignal.connect(this, this.mySignalSlot);
In this case, mySignalSlot should have the same signature than mySignal declaration at the C++ class side (well, "same signature" would mean same number of parameters as javascript is not typed, so you won't need to declare a type for each of them).
What's really usefull here is to pass JSon objects. In case you need to pass big amount of data you can use base64 encoding. For images, QTWebKit supports natively QImage and QPixmap classes; these last two are natively encoded as complex javascript objects by QTWebKit Bridge engine.
I have built a small compiler, for a statically typed language. After understanding how a static language works, I'm having trouble getting my head into dynamic languages like groovy.
While constructing my compiler, I know that once I generate the machine level-code there is no way of changing it! (i.e its run-time).
But how does Groovy do this magical stuff like inferring type in statements like:
def a = "string"
a.size()
As far as I'm concerned, groovy has to find the type a is of string before running the line a.size(). It seems that it does so in compile time (while constructing AST)! But the language is called dynamic.
I'm confused, kindly help me figure out.
Thanks.
Groovy doesn't simply "call" a method, but dispatches it through the meta-object protocol. The method invocation is sent as a message to the object, which can respond to it or not. When using dynamic typing, it doesn't matter the object type, only if it responds to that message. This is called duck typing.
You can see it (though not easily) when you decompile Groovy code. You can compile using groovyc and decompile using other tool. I recommend jd-gui. You won't see the method being called explicitly, because of Groovy's method caching (it is done this way to achieve Groovy's neat performance).
For a simple script like:
def a = "abcdefg"
println a.substring(2)
This will be the generated code:
CallSite[] arrayOfCallSite = $getCallSiteArray(); Object a = "abcdefg";
return arrayOfCallSite[1].callCurrent(
this, arrayOfCallSite[2].call(a, Integer.valueOf(2))); return null;
And the method call is "dispatched" to the object, not called directly. This is a similar concept to Smalltalks and Ruby method dispatch. It is because of that mechanism that you can intercept methods and property access on Groovy objects.
Since Groovy 2, Groovy code can be statically compiled, thus acting like your compiler.
Is there any tool which provides Java dynamic code generation and that also supports generics?
Javassist for example, is the kind of tool that I need, but it does not support generics.
I wrote a small lib which uses the Java 6 Compiler API, however as far as I know it depends on JDK. Is there a way to specify another compiler? Or to ship with my application only the parts that I need to invoke with the Java Compiler API?
It seems you can manipulate and read generic info with Javaassist. See
http://www.mail-archive.com/jboss-user#lists.jboss.org/msg101222.html
[jboss-user] [Javassist user questions] - Re: Altering Generics Information of Methods using Javassist
SimonRinguette
Thu, 20 Dec 2007 12:22:14 -0800
I have done further reading on how this is implemented by the compiler and
finally found out the answer I was looking for.
You can defenitely do that with javaassist. The key class is
javassist.bytecode.SignatureAttribute.
From a CtMethod, i've obtained the methodInfo I add a Signature attribute. You can do it with something like:
CtMethod method = ....
MethodInfo methodInfo = method.getMethodInfo();
SignatureAttribute signatureAttribute = new
SignatureAttribute(methodInfo.getConstPool(),
"()Ljava/util/List<Ljava/lang/String;>;");
methodInfo.addAttribute(signatureAttribute);
If your more interesed in reading the signature with the generics inside, you
can use the methodInfo.getAttribute(SignatureAttribute.tag).
I hope this helped.
If you are comfortable with writing bytecode then ASM is quite a good library for that kind of thing. That will let you generate a class file on the fly without having to worry about the nitty-gritty of the classfile format. You can then use a classloader to dynamically load it into your application.
If I recall correctly, it is sufficient to have tools.jar in the classpath in order to use the Java compiler at runtime.
Actually, javaassist can handle generics using SignatureAttribute.
SignatureAttribute.Type retType = new SignatureAttribute.BaseType(Void.TYPE.getName());
SignatureAttribute.Type[] argType = getArgType();
SignatureAttribute.MethodSignature signature = new SignatureAttribute.MethodSignature(null, argType, retType, null);
method.setGenericSignature(signature.encode());
This project has a lot of very good examples. Hop they are helpful.