This is Test class.
package com.reflection;
import com.reflection.test.A
public class Main {
public void setA() {
A a = new A();
}
}
Then, I used ClassLoader for accessing and manipulating classes, fields, methods, and constructors as the code below
Class cls = cl.loadClass("com.reflection.Main");
Actually I really want to get A class by using cls and already tried to use getDeclaredClasses and getClasses but the result was nothing.
You can't do that with pure Java reflection. Reflection will let you look at classes and their members, but not at the code inside a method.
The easiest thing to do is probably to do javap -v somewhere in the build process, parse the output for qualified class names and store them in a property file somewhere.
The harder version is to use a byte code tool like asm or ByteBuddy, write a visitor over all instructions in your class and store all classes from all instructions in a Map. While this is theoretically the elegant approach, it will probably be a nightmare.
Related
It is possible in plain Java to override a method of a class
programmatically at runtime (or even create a new method)?
I want to be able to do this even if I don't know the classes at compile time.
What I mean exactly by overriding at runtime:
abstract class MyClass{
public void myMethod();
}
class Overrider extends MyClass{
#Override
public void myMethod(){}
}
class Injector{
public static void myMethod(){ // STATIC !!!
// do actual stuff
}
}
// some magic code goes here
Overrider altered = doMagic(
MyClass.class, Overrider.class, Injector.class);
Now, this invocation...
altered.myMethod();
...would call Injector.myMethod() instead of Overrider.myMethod().
Injector.myMethod() is static, because, after doing "magic"
it is invoked from different class instance (it's the Overrider),
(so we prevent it from accessing local fields).
You can use something like cglib for generating code on-the-fly
In java6 has been added the possibility to transform any already loaded class. Take a look at the changes in the java.lang.instrument package
For interfaces there is java.lang.reflect.Proxy.
For classes you'll either need a third-party library or write a fair bit of code. Generally dynamically creating classes in this way is to create mocks for testing.
There is also the instrumentation API that allows modification of classes. You can also modify classes with a custom class loader or just the class files on disk.
I wrote an article for java.net about how to transparently add logging statements to a class when it is loaded by the classloader using a java agent.
It uses the Javassist library to manipulate the byte code, including using the Javassist compiler to generate extra bytecode which is then inserted in the appropriate place, and then the resulting class is provided to the classloader.
A refined version is available with the slf4j project.
If I got it right, the main problem that concerns you is how to pass a static method delegate (like in C#), through the instance interface method.
You can check this article: A Java Programmer Looks at C# Delegates (archived), which shows you how to get a reference to your static method and invoke it. You can then create a wrapper class which accepts the static method name in its constructor, and implements your base class to invoke the static method from the instance method.
I have a fairly large Java code base (~15k files) that I do not have access to the source for, however, I would like to modify certain classes at runtime and inject code into certain methods to also call my code.
Due to technical issues, I can't decompile/recompile and go from there. The class files are loaded by native code and are extracted from a custom archive format and loaded using a custom class loader. I can however execute Java code in the context of their JVM instance fairly easily.
My goal is to do something like below:
For example, say in there code there is a class:
class Theirs {
public Theirs() {
//....
}
public String getName() {
return "Theirs";
}
}
And in my code I have:
class Mine
{
public static Theirs theirs_ = null;
public static void myMethod(Theirs theirs) {
theirs_ = theirs;
}
}
I would like to modify every instance of Theirs to behave as such:
class Theirs {
public Theirs() {
Mine.myMethod(this);
}
}
So that I can then do something like:
System.out.println(Mine.theirs_.getName());
I thought that CGLib Proxies would enable this, but with Proxies, the overhead is high due to string comparisons for methods that may be called hundreds thousands of times a second and anyways, I discovered that in order to have an instance of an enhanced object, you need to instantiate them yourself.. IE: not all instances of the class you enhanced are actually enhanced such as:
public static void main( String[] args )
{
Object proxy = Enhancer.create(Object.class, new HashCodeAlwaysZeroMethodInterceptor());
System.out.println(new Object().hashCode());
System.out.println(proxy.hashCode());
}
The first println prints a real objects hash, not 0 as intended.
So now I am thinking that what I need to do is write my own (or modify theirs) ClassLoader that looks for the classes I am interested in modifying, inject my modifications and go from there using something like ASM. (I've done something similar using JVMTI and C++, but the compile/debug process for that is extremely time consuming)
Before I do that however, I was hoping that there was something that worked similar to how CGLib proxies work, in that the library takes care of the required bytecode modifications, but that doesn't require me to actually instantiate an instance of said enhanced class.
I don't know if CGLIB is ideal for injecting Java code into Java classes - but there are a couple of framework like f.e. javassist available which provide a Java centric way to inject code into non-sealed Java classes: http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/
For example, I had to create a Plugin mechanism for a university course once where I used javassist therefore. Hope the code example is helpful: https://github.com/RovoMe/PluginApplication/blob/master/PluginFramework/PluginCore/src/main/java/at/rovo/core/classloader/InjectionLoaderStrategyDecorator.java
package com.companyxyz.api.person;
public class Man {
public var1;
public var2;
...
private static void createAuth() {
...
}
// public methods go here
...
}
I want to create a new public method that accesses the private method, createAuth, but in a different file. Is there a way to create this new method without writing it or accessing it via an extended class?
Thank you.
No. You can't access a private method from an other class. Because it's ... private.
A private method is not accessible to any external classes, (this includes subclasses).
A workaround might be to use reflection, however this isn't a generally recommended approach for a number of reasons (brittleness, performance problems, breaking encapsulation, etc).
There is no clean and recommended general way to do this in Java. private is private.
But you did not state why you want to do this and what the specific constraints are. Therefore I throw two options into the mix:
You can decompile the class file for Man, set everything you want to protected or public and recompile (and repackage into a jar file). Perhaps there is no need to decompile, perhaps some bit manipulation on the class file can do the job, too.
You can write a custom ClassLoader with a bytecode manipulation library to modify the bytecode of the class at runtime. Then you can also add additional access paths to the stuff you want. Note however that this is extremely advanced/complicated stuff.
Both ways are nothing you can use / should use for normal applications or the usual framework.
Using reflection you can get pretty much everything relating to a class. You can get all the declared methods, fields and classes (and possibly even more), but i couldn't find a way to reflect on a method so i could find out what classes that method might be using.
Essentially i would like to find out all dependencies to other classes that a given class has.
Example:
Given the following code:
import com.yada.yada.yada.SomeClass
public class MyClass
{
public MyClass
{
new SomeClass();
}
}
How can i find out that MyClass is using SomeClass in its constructor?
I was trying to think of a way to get all import statements defined in a class file but i couldn't find anything that way either. But, assuming there's a way to somehow dig up all import statements defined in a class file, how would one find out about classes defined in the same package, which do not require an import statement?
EDIT:
Scenario: The goal is to send the bytecode of this class (MyClass) to another process. This other process then takes in the bytecode and loads the class (MyClass) using class loaders, and so on. The problem is that when i try to create and run an instance of MyClass in the other process it fails because it cannot find a definition for SomeClass.
If SomeClass were a member of MyClass it wouldn't be a problem but since the only reference to it lies in a method, there's no way to get to it via reflection?
I think the closest you can come to getting all of a class's dependencies is by hooking into the class loader mechanism and recording what classes get loaded when the class you're examining is instantiated and its methods are called. Of yourse, you'd transitively also get all the classes that it indirectly depends on, but depending on what you want to do with the information, that may be what you actually need.
But it's impossible to do for all cases (just imagine a method that uses Class.forName() to ask for a random class name every time it's called).
how would one find out about classes defined in the same package
That's actually impossible to do in general, since the class loader concept really only allows asking for a fully qualified class name, and either getting that class or a ClassNotFoundException. Classes can be loaded from a webserver (in the case of applets) or generated on the fly, so you cannot know whether a specific class exists except by asking for it.
You can't (unless you decompile the bytecode). A local variable is not tied to any class instance, and it does not even exist for most of the lifetime of the class or its instances, so you can't access it via reflection.
What are you trying to achieve? Maybe if you tell us about your actual problem, rather than a perceived solution, we are better able to help.
Reflection does not help you here. The only way I can think of that you can achieve this is through a byte code tool like asm.
Create a ClassVisitor that gathers dependencies from
Class declarations
Annotations
Local variable declarations
Field declarations
Method declarations
Method invocations
(have I forgotten anything?)
Is there a way to obtain the Java source code from a class name?
For example, if I have access to the library with the class java.io.File, I want its source code.
I am working on a kind of parser and I need the source at execution time. I have also to search it recursively.
Say the aforementioned class has this method:
int method (User user) {...}
I would need to obtain User's source code, and so on and so forth with its inner classes.
Is there any way to obtain the java source from a class name? For example:...
You may want one of several possible solutions. Without knowing what you really want to do with the information, we can't be very precise with our recommendations, but I'd start by steering you away from source code if possible. JSE source code is available online, as are many open source libraries, but that may not always be the case. Additionally, you'll need to keep it all organized when you want to find it, much like a classpath, whereas the Class objects are much easier to get hold of, and manipulate, without having to parse text again.
Reflection
If you just need information about a class at runtime, just use the Java Reflection API. With it, given a Class object you can, for example, get the types of a specific field, list all fields and iterate over them, etc...:
Class clazz = User.class;
Field field = clazz.getDeclaredField("var");
System.out.println(field.getType().getName());
Reflection is useful for discovering information about the classes in the program, and of course you can walk the entire tree without having to find source code, or parse anything.
Remember you can lookup a class object (as long as it's on the classpath at runtime) with Class.forName("MyClass") and reflect on the resulting Class.
Bytecode Manipulation
If you need more than information, and actually want to manipulate the classes, you want bytecode manipulation. Some have tried to generate source code, compile to bytecode and load into their program, but trust me - using a solid bytecode manipulation API is far, far easier. I recommend ASM.
With it, you can not only get information about a class, but add new fields, new methods, create new classes... even load multiple variations of a class if you're feeling self-abusive. An example of using ASM can be found here.
Decompilation
If you really, really do need the source, and don't have it available, you can decompile it from a class object using one of the various decompilers out there. They use the same information and techniques as the above two, but go further and [attempt] to generate source code. Note that it doesn't always work. I recommend Jode, but a decent list, and comparison of others is available online.
File Lookup
If you have the source and really just want to look it up, maybe all you need is to put the .java files somewhere in a big tree, and retrieve based on package name as needed.
Class clazz = User.class;
String path = clazz.getPackage().getName().replaceAll("\\.","/");
File sourceFile = new File(path, clazz.getName() + ".java")
You want more logic there to check the class type, since obviously primatives don't have class definitions, and you want to handle array types differently.
You can lookup a class by name (if the .class files are on your classpath) with Class.forName("MyClass").
You can get a good approximation of the source from a class file using the JAVA decompiler of your choice. However, if you're really after the source of java.io.File then you can download that.
The best and simplest bet can be javap
hello.java
public class hello
{
public static void main(String[] args)
{
System.out.println("hello world!");
world();
}
static public void world()
{
System.out.println("I am second method");
}
}
do a javap hello and you will get this:
Compiled from "hello.java"
public class hello extends java.lang.Object{
public hello();
public static void main(java.lang.String[]);
public static void world();
}
Yes, if you download the source code. It's available for public download on the official download page.
If you're using Eclipse whenever you use the class you could right click > View Source (or simply click the class > F3) and it'll open a new tab with the source.
You can print the resource path from where the class was loaded with
URL sourceURL=obj.getClass().getProtectionDomain().getCodeSource().getLocation();
It will be a .class file , .jar,.zip, or something else.
So what you're trying to do is get the Java class at execution. For this, you need Java reflections.
If your goal is to get information about what's in a class, you may find the Java reflection API to be an easier approach. You can use reflection to look up the fields, methods, constructors, inheritance hierarchy, etc. of a class at runtime, without needing to have the source code for the class available.
Is there any way to obtain the java source from a class name?
The answer is complicated, not least because of the vagueness of your question. (Example notwithstanding).
In general it is not possible to get the real, actual Java source code for a class.
If you have (for example) a ZIP or JAR file containing the source code for the classes, then it is simple to extract the relevant source file based on the classes fully qualified name. But you have to have gotten those ZIP / JAR files from somewhere in the first place.
If you are only interested in method signatures, attribute names and types and so on, then much of this information is available at runtime using the Java reflection APIs. However, it depends on whether the classes were compiled with debug information (see the -g option to the javac compiler) how much will be available. And this is nowhere like the information that you can get from the real source code.
A decompiler may be able to generate compilable source code for a class from the bytecode files. But the decompiled code will look nothing like the original source code.
I guess, if you have a URL for a website populated with the javadocs for the classes, you could go from a class name, method name, or public attribute name to the corresponding javadoc URL at runtime. You could possibly even "screen scrape" the descriptions out of the javadocs. But once again, this is not the real source code.