Java: Adding fields to class at runtime & compiletime? - java

Rewriting this for greater clarity.
R.java is a great resource in Android. It's basically cheating, by dynamically changing at compile time to provide access to all of your resources.
It would be awesome to have something like this available for applications running core Java. However, I understand that R.java does some crazy hackery to make this work.
So, here are my goals. If anyone has any ideas to point me in the right direction, that would be great.
1) Public static fields that link to resources defined by the developer.
2) The fields are created dynamically, ie they are not hard-coded into existence.
3) The dynamic creation occurs at compile time, so the following statement would be accepted by the compiler: MyRJava.resourceName.
Is this even remotely possible? Where would I start looking to see if it can be done?

Java doesn't support this, but Groovy does. As a Java developer, you should have no problem picking up Groovy for something like this. One of the nice things about Groovy is that it coexists very well with Java code. Where I work, we frequently go back and forth between the two languages.

Remotely possible. We were successfully using APT and Maven to set up a compile time goal which generates additional Java classes. This however not a real dynamic class generation, as we're doing everything in compile time.
The advantage is that after saving (and the code generator has run), you can use all the genarated fields normally (i.e. in autocomplete, and so on).
It is also possible to create something similar in runtime, i.e. you can create a class file, compile it, and then get access to its fields and methods via reflection. In this case however accessing to the genrated fields are more problematic - and finally you'd better go with a simple Map to hold "resource ids" like R.java.

Related

Java Imports, Assembly (Krakatau), and Source Code

So here's my situation:
I am running a Java Client/Server architecture that has high CPU usage and I'm trying to reduce the lag time on the main "server" thread. I have been profiling the server with YourKit to identify the CPU-hogging code.
The problem is:
I am using someone else's code, and because of the way it is written, it is impossible to decompile, then recompile without using a special obfuscator which I do not have access to (no I am not violating any copyrights or anything).
What I am currently doing:
To modify the class files without worrying about obfuscation, I have been using Storyyeller's amazing Krakatau decompiler (https://github.com/Storyyeller/Krakatau) to disassemble class files into assembly files.
I manually edit the .j assembly files while looking at a Jasmin reference page (which takes FOREVER and I often mess up), then reassemble them into class files and run them again.
What I want to do:
Instead of painstakingly editing the assembly, I was wondering, does anyone know of a way to convert .java Source Code to .j Assembly code?
Also, if I simply decompile the .class files, is it possible for me to simply recompile them even though the packages for the imports do not exist?
import com.bazinga.*;
public class MainThread{}//compile this even though package com.bazinga doesn't exist?
If anyone knows ANY WAY I could do this, I would really appreciate it!
Instead of painstakingly editing the assembly, I was wondering, does anyone know of a way to convert .java Source Code to .j Assembly code?
Yes and no. The obvious answer is that you can just compile your code and then disassemble the resulting classes. However, this is not always helpful, because compilation can be context dependent (such as inlining static final constants, or handling of nested classes). Additionally, if you plan to add your code into an existing method, you have to be careful to not use existing local variable slots or clobber the operand stack.
My best advice is to try to isolate your modifications as much as possible. For example, if you want to add code to the jar, instead of inserting it into an existing class, just write the code you want to add in Java, compile it and add the classfiles in. Then modify the target class to call into your own class.
As for imports, you can compile against stubs. Just create a dummy class with the name you want, and optionally dummy methods for anything you need to call. The implementations can just be {throw null;} or similar, since you won't actually be executing them ever, they just need to exist to satisfy the compiler during compilation.

How to find all initializations of instance variables in a Java package?

I'm in the midst of converting a legacy app to Spring. As part of the transition, we're converting our service classes from an "instantiate new ones whenever you need one" style to a Springleton style, so I need a way to make sure they don't have any state.
I'm comfortable on the *nix command-line, and I have access to IntelliJ (this strikes me as a good fit for Structural Search and Replace, if I could figure out how to use it), and I could track down an Eclipse install, if that would help. I just want to make absolutely sure I've found all the possible problems.
UPDATE: Sorry for the confusion. I don't have a problem finding places where the old constructor was being called. What I'm looking for is a "bullet-proof" why to search all 100+ service classes for any sort of internal state. The most obvious one I could think of (and the only one I've really found so far) is cases where we use memoization in the classes, so they have instance variables that get initialized internally instead of via Spring. This means that when the same Springleton gets used for different requests, data can leak between them.
Thanks.
In Eclipse you can just right click on a variable/type and there is an option for References (or Declarations) -> (Workspace / Project / Hierarchy) which can help you find all instances of it neatly.
I would suggest using Eclipse's built in refactoring tool, it will do its best to change every instance associated to the class accordingly. I would go a step further and rename the class of that you want to change so, at worst case, a full compile would fail and you can easily fix any of those issues.

Finding new Java class at runtime

I have a functionality that I wish to provide to a customer for a software mockup that we are preparing - and I want to know if it's
possible
intelligent (a.k.a. not stupid)
the best thing
I want the customer to be able to write a java class that implements my Computable interface and stick it in some predetermined folder. This folder will contain the .java files rather than .class files. Then, at runtime, I want my program to search that folder and extract all of the Computables from that folder and store them in a map from the name of the Computable to the Computable object. The Computable should only have a default constructor and the it interface will only have one method called compute which maps an array of Object to an Object.
The Java Compiler API introduced in Java SE 6 should give you what you need.
You may find Google Reflections useful to find classes implementing/extending a certain interface/superclass in the classpath. It's then as straightforward as
Reflections reflections = new Reflections("my.project.prefix");
Set<Class<? extends SomeClassOrInterface>> subTypes = reflections.getSubTypesOf(SomeClassOrInterface.class);
Then, to test if it indeed has a no-arg default constructor, just check for each if Class#newInstance() doesn't throw any exception.
There are several suggestions provided as answers to this question.
Here too On-the-fly, in-memory java code compilation for Java 5 and Java 6
If it's easy enough to compile at runtime that would be fine.
You can use javax.tools to do the compilation as needed. Create dynamic applications with javax.tools may help, too. It's also possible to do it in memory.
One caveat: using the compiler creates a dependency on the JDK; the JRE alone is insufficient.
take a look: Find Java classes implementing an interface
I think this would be simpler if you allowed your customer to type in a code declaration using something like Groovy, which is Java-ish enough, and easy to execute at runtime from a String value.
It's easy enough to iterate through the list of files in a folder. Someone mentioned that it's possible to call the Java compiler from Java (if you re-distribute the JDK, which I think is a point whose legality needs checking!!) That's much of the battle.
You seem to have a fixed model in your mind where only files fulfilling a certain interface are extracted from the folder. I think this is where your method needs to give a little. The sensible way (IMO) to do this would be to compile all files in that folder, and then with their classes stashed away somewhere, you can load and reflect them and then determine which of them "do" the interface and which don't. Those that don't will have been needlessly loaded into your JVM, but unless it's intentionally very space-wasteful, code you don't execute can't harm your program.
Having determined which ones do the computable thing, you can then store those classes (or instances thereof) in a Collection and do whatever you like with them. You simply ignore the other ones.
You could use BeanShell. This library is small and doesn't require the JDK. It is used in a number of IDE and web servers. The latest version appears to have the support you need loading .java files from the class path. (Still in beta)

(2009) - Tool to deobfuscate Java codes

Is there a tool to deobfuscate java obfuscated codes?
The codes is extracted from a compiled class but they are obfuscated and non-readable.
First step would be to learn with which tool it was obfuscated. Maybe there's already a "deobfuscator" around for the particular obfuscator.
On the other hand, you can also just run an IDE and use its refactoring powers. Rename the class, method and variable names to something sensitive. Use your human logical thinking powers to figure what the code actually represents and name them sensitively. And the picture would slowly but surely grow.
Good luck.
Did you try to make the code less obscure with Java Deobfuscator (aka JDO), a kind of smart decompiler?
Currently JDO does the following:
renames obfuscated methods, variables, constants and class names
to be unique and more indicative of
their type
propogates changes throughout the entire source tree (beta)
has an easy to use GUI
allow you to specify the name for a field, method and class (new feature!)
Currently JDO does not do the
following (but it might one day)
modify method bytecode in any way
Not to gravedig but I wrote a tool that works on most commercial obfuscators
https://github.com/Contra/JMD
I used Java Deobfuscator (aka JDO) but it has a few bugs. It can't work with case sensitive file names.
So I've changed the source and uploaded a patch for that in sourceforge.
The patch, Download
Most likely only human mindpower to make sense of it. Get the best decompiler available and ponder on its output.
Maybe it will work on Unix/Linux/MacOS?
If so, you could move one step of your process to a VM, in where you unpack the code, before you rename the too long names. How long is the file name limit on Windows?

On-the-fly, in-memory java code compilation for Java 5 and Java 6

How can I compile java code from an arbitrary string (in memory) in Java 5 and Java 6, load it and run a specific method on it (predefined)?
Before you flame this, I looked over existing implementations:
Most rely on Java 6 Compiler API.
Those that don't, rely on tricks.
Yes, I checked out commons-jci. Either I'm too dense to understand how it works, or it just doesn't.
I could not find how to feed the compiler my current class path (which is quite huge).
On the implementation that worked (in Java 6), I could not find how to correctly load inner classes (or inner anonymous classes).
I'd quite like it if the entire thing was in-memory, as the thing runs on multiple environments.
I'm sure this has been solved before, but I can't find anything that looks even half-production quality on google (except jci, which, as I've said before, I haven't managed to use).
Edit:
I looked over JavaAssist - I need inner classes, Java 5.0 language level support and compiling with the entire classpath. Also, I'd like to create new classes on the fly. I
might be mistaken, but I couldn't find how to do this with JavaAssit.
I'm willing to use a file-system based solution (calling javac) but I don't know how to divine the classpath, nor how to later load the files (which are not in my classpath) with a special classloader that can be recycled for multiple invocations. While I do know how to research it, I'd prefer a ready solution.
Edit2:
For now, I'm content with BeanShell "evaluate". Apparently it does everything I need it to (get a string, evaluate it in the context of the 'current' classpath. It does miss some of Java 5 features, but it can use enums (not define) and compiled 'generic' (erased) classes, so it should be enough for what I want.
I don't want to mark the answer as accepted yet since I do hope for a better solution to come up.
Edit3: Accepted the beanshell suggestion - it really works wonderfully.
JCI looks fine. This code snippet should be your base:
JavaCompiler compiler = new JavaCompilerFactory().createCompiler("eclipse");
MemoryResourceReader mrr = new MemoryResourceReader();
mrr.add("resource name string", yourJavaSourceString.getBytes());
MemoryResourceStore mrs = new MemoryResourceStore();
CompilationResult result = compiler.compile(sources, mrr, mrs);
// don't need the result, unless you care for errors/warnings
// the class should have been compiled to your destination dir
Any reason this should not work?
Edit: added a MemoryResourceStore to send the compiled class output to memory, like requested.
Also, setting javac settings, like classpath in your case, can be done via setCustomArguments(String[] pCustomArguments) in JavacJavaCompilerSettings class.
You might want to check out Janino as well.
From their website:
Janino is a compiler that reads a JavaTM expression, block, class body, source file or a set of source files, and generates JavaTM bytecode that is loaded and executed directly. Janino is not intended to be a development tool, but an embedded compiler for run-time compilation purposes, e.g. expression evaluators or "server pages" engines like JSP.
http://www.janino.net/
Im currently using it in a pretty large mission critical project and it works just fine
If you're not completely tied to compiling, solutions like Beanshell, groovy and the other scripting languages are easily embedded (in-fact, java has built-in support for plugging in a scripting language so your code doesn't even know what language the script is written in)
Beanshell should run any 100% java code IIRC, and I believe Groovy can run most java code--possibly all.
Javassist might interest you
Run inside a web container like Tomcat and first generate a JSP page, and then invoke it.
This also allow you to get rid of the old class definitions by simply overwriting the JSP page instead of having your classloader slowly run full.
Is the "in-memory" requirement due to speed or due to not changing the code base?
ECJ Eclipse Java Compiler
Eclipse provides and uses its own compiler that is not javac
The Eclipse compiler is used inside the IDE (Eclipse)
The Eclipse compiler can also be used as a pure batch compiler
outside of Eclipse
Compile a source file
$ java -jar ecj-3.5.2.jar HelloWorld.java

Categories

Resources