write java object into class file - java

Is there any way to write a loaded Java object into a .class file or is there any other type of file that can easily be read to represent an instance's properties.
For example, CGLIB will create an proxy bean which extends another, i really want to export this enhanced bean out to a file to see how it was enhanced.

to use HSDB tool in JDK
keep your program running
run HSDB tool:
java -classpath "$JAVA_HOME/lib/sa-jdi.jar" sun.jvm.hotspot.HSDB
input the program pid
choose tools and you can save .class file,that is what you want

For cglib, instances can only be serialized and only if the instance's method interceptors support serialization. There is no other way.
In order to get hold of a cglib-generated class file, you can call the
void generateClass(ClassVisitor v)
method. This method can take an ASM ClassWriter which can after calling the method emitt a byte array representing the class file. This class file by itself does however not help you much as cglib needs to initialize the class explicitly, e.g. inject the callback handlers into the class's fields. This is done inside of the library. However, with the class file at hand and with debug-mode introspection, you can add the pieces and understand how your enhanced class works.
Finally, if I can recommend you an alternative to cglib where all this is easier, have a look at Byte Buddy which has a straight-foward API for extracting a class file and also offers so-called LoadedTypeInitializers in parallel to this class file. The latter initializers contain any setup logic for a class and are easy to read. Also, they are themselfs serializable.

Related

Lightweight scripting support in Java

I was wondering if it's possible to have some sort of scripting in Java that can hook text files stored outside and have them imported into the application as a class object.
Some context : I'm developing a scientific calculator that supports custom functions and operations, while this functionality is available to programmers as they can easily just implement the necessary interface and deal with it. however I recently received the request to add a new feature where the general users should be able to write their own custom functions/operations or both and the app should be able to interpret them and have them imported into its list of functions.
I was initially planning on allowing the users to just be able to write a plain text file and store it in a specific folder, and the app will be able to load this text files as an input stream, I was going for a string token parsing sort of approach but I have no idea how will I make this work or how will I go about converting them into objects(implenting those necessary interfaces), if anyone can hint me on how such a thing would be accomplished or if it's even possible.
And no code to show for now.
The best match for this requirement I know is Java's Reflection.
Your calculator should define an interface that anyone can implement.
The implementation class can be later placed in your calculator classpath so it can detect it at runtime and instantiate it using reflection.
As the implementation classes all implements the known interface, you can cast the instance to that interface and execute the known method.
This way you get to run external code, unknown to the calculator which can be added dynamically.
So the steps are:
Define an interface e.g:
public interface CalculatorExecutable {
void runMe();
}
Others can write classes that implement this interface.
public class MyOp implements CalculatorExecutable {
public void runMe() {
/* any implementation here */
}
}
As you mentioned, you can read all the class names from a directory you designate, simply read all the files in that directory and filter for only those files with .class extension
After you instantiate with Class.forName( classNameGoesHere ); you can cast to your interface and execute your "runMe" method.

How can i use redefineClasses() method in javaagents

I have been using premain() with addTransformer(). Since, it gives javassist.ClassNotFound exceptions for certain classes when i run the agent with a server, i thought to try the agentMain() with redefineClasses(). I went through many links, but so far i am unable to find a piece of code that gives me clear idea on how to set up a simple java agent using these two methods. Some help would be really appreciated.
Can we use redefineClasses() with premain()? (When we use redefineClasses() do we still need the transform method?)
I am trying to instrument set of methods of set of classes, where i know the fully qualified name of those classes as com.test.Foo. I wanted to instrument them without going through the entire set of classes loaded onto JVM. I have been reading those documents back and forth, but still i am unable to get a clear idea on how to use that redefineClasses method?
You can call redefineClasses from anywhere, also from a premain method which is nothing but an extension to a normal Java program run by the same JVM process previous to a main method.
A trivial example for running a redefinition is:
instrumentation.redefineClasses(new ClassDefinition(Foo.class, new byte[] {...}));
This way, Foo is set to be represented by the byte array that must contain a valid class file for Foo where all signatures of fields and methods are the same as by the loaded Foo.class. You can use a tool like ASM for instrumenting the class.
If you really only want to instrument Foo, then this might just be the way to go instead of using a ClassFileTransformer.

A better way to call static methods in user-submitted code?

I have a large data set. I am creating a system which allows users to submit java source files, which will then be applied to the data set. To be more specific, each submitted java source file must contain a static method with a specific name, let's say toBeInvoked(). toBeInvoked will take a row of the data set as an array parameter. I want to call the toBeInvoked method of each submitted source file on each row in the data set. I also need to implement security measures (so toBeInvoked() can't do I/O, can't call exit, etc.).
Currently, my implementation is this: I have a list of the names of the java source files. For each file, I create an instance of the custom secure ClassLoader which I coded, which compiles the source file and returns the compiled class. I use reflection to extract the static method toBeInvoked() (e.g. method = c.getMethod("toBeInvoked", double[].class)). Then, I iterate over the rows of the data set, and invoke the method on each row.
There are at least two problems with my approach:
it appears to be painfully slow (I've heard reflection tends to be slow)
the code is more complicated than I would like
Is there a better way to accomplish what I am trying to do?
There is no significantly better approach given the constraints that you have set yourself.
For what it is worth, what makes this "painfully slow" is compiling the source files to class files and loading them. That is many orders of magnitude slower than the use of reflection to call the methods.
(Use of a common interface rather than static methods is not going to make a measurable difference to speed, and the reduction in complexity is relatively small.)
If you really want to simplify this and speed it up, change your architecture so that the code is provided as a JAR file containing all of the compiled classes.
Assuming your #toBeInvoked() could be defined in an interface rather than being static (it should be!), you could just load the class and cast it to the interface:
Class<? extends YourInterface> c = Class.forName("name", true, classLoader).asSubclass(YourInterface.class);
YourInterface i = c.newInstance();
Afterwards invoke #toBeInvoked() directly.
Also have a look into java.util.ServiceLoader, which could be helpful for finding the right class to load in case you have more than one source file.
Personally, I would use an interface. This will allow you to have multiple instance with their own state (useful for multi-threading) but more importantly you can use an interface, first to define which methods must be implemented but also to call the methods.
Reflection is slow but this is only relative to other options such as a direct method call. If you are scanning a large data set, the fact you have to pulling data from main memory is likely to be much more expensive.
I would suggest following steps for your problem.
To check if the method contains any unwanted code, you need to have a check script which can do these checks at upload time.
Create an Interface having a method toBeInvoked() (not a static method).
All the classes which are uploaded must implement this interface and add the logic inside this method.
you can have your custom class loader scan a particular folder for new classes being added and load them accordingly.
When a file is uploaded and successfully validated, you can compile and copy the class file to the folder which class loader scans.
You processor class can lookup for new files and then call toBeInvoked() method on loaded class when required.
Hope this help. (Note that i have used a similar mechanism to load dynamically workflow step classes in Workflow Engine tool which was developed).

Java class for implementing a SAX Parser with inner classes

For a college assignment I need to write a SAX parser and a filter that reads the original XML file then creates a new modified one. The assignment requires that my program need to be run by console with "java Sax inputFileDestination OutputFileDestination" and it requires that there is only one file. I means I need to implement the interfaces with in the Sax.java. I am familiar with the inner classes but I dont know how to implement this with a main method in the outer class.
Any sugestions?
Since this is an assignment, I'm not going to post any code, but explain how to do it.
I don't think you need an inner class at all to do this. Your class will have a main method, which creates a SAXParser, and registers itself (this) as a callback. You will then implement the SAX methods you desire (startElement, endElement, characters) from HandlerBase.
All your're doing is writing a SAXParser, and then tacking a main() method on it, so it will run from the command line.
Consider creating a MySAXParser class with a usage outside in another class having a main. Then place that main method inside your MySAXParser class as test code.
XML Parsers deliver a jar with a META-INF/MANIFEST.MF using the SPI (Service Provider Interface). You might think of doing the same thing as a bonus.
Other inner classes can be private static if they are independent, or just private storing an extra outer MySAXParser.this; so one error often made is forgetting static.

How can I run my code upon class load?

Is there a feasible way to get my own code run whenever any class is loaded in Java, without forcing the user explicitly and manually loading all classes with a custom classloader?
Without going too much into the details, whenever a class implementing a certain interface read its annotation that links it with another class, and give the pair to a third class.
Edit: Heck, I'll go to details: I'm doing an event handling library. What I'm doing is having the client code do their own Listener / Event pairs, which need to be registered with my library as a pair. (hm, that wasn't that long after all).
Further Edit: Currently the client code needs to register the pair of classes/interfaces manually, which works pretty well. My intent is to automate this away, and I thought that linking the two classes with annotations would help. Next, I want to get rid of the client code needing to keeping the list of registrations up to date always.
PS: The static block won't do, since my interface is bundled into a library, and the client code will create further interfaces. Thus, abstract classes won't do either, since it must be an interface.
If you want to base the behavior on an interface, you could use a static initializer in that interface.
public interface Foo{
static{
// do initializing here
}
}
I'm not saying it's good practice, but it will definitely initialize the first time one of the implementing classes is loaded.
Update: static blocks in interfaces are illegal. Use abstract classes instead!
Reference:
Initializers (Sun Java Tutorial)
But if I understand you right, you want the initialization to happen once per implementing class. That will be tricky. You definitely can't do that with an interface based solution. You could do it with an abstract base class that has a dynamic initializer (or constructor), that checks whether the requested mapping already exists and adds it if it doesn't, but doing such things in constructors is quite a hack.
I'd say you cleanest options are either to generate Code at build time (through annotation processing with apt or through bytecode analysis with a tool like asm) or to use an agent at class load time to dynamically create the mapping.
Ah, more input. Very good. So clients use your library and provide mappings based on annotations. Then I'd say your library should provide an initializer method, where client code can register classes. Something like this:
YourLibrary.getInstance().registerMappedClasses(
CustomClass1.class,
CustomClass2.class,
CustomClass3.class,
CustomClass4.class
)
Or, even better, a package scanning mechanism (example code to implement this can be found at this question):
YourLibrary.getInstance().registerMappedClassesFromPackages(
"com.mycompany.myclientcode.abc",
"com.mycompany.myclientcode.def"
)
Anyway, there is basically no way to avoid having your clients do that kind of work, because you can't control their build process nor their classloader for them (but you could of course provide guides for classloader or build configuration).
If you want some piece of code to be run on any class loading, you should:
overwrite the ClassLoader, adding your own custom code at the loadClass methods (don't forget forwarding to the parent ClassLoader after or before your custom code).
Define this custom ClassLoader as the default for your system (here you got how to do it: How to set my custom class loader to be the default?).
Run and check it.
Depending on what kind of environment you are, there are chances that not all the classes be loaded trouugh your custom ClassLoader (some utility packages use their own CL, some Java EE containers handle some spacific areas with specific classLoaders, etc.), but it's a kind of aproximation to what you are asking.

Categories

Resources