Let's say I have the following classes:
class A {
static public String a;
}
class B {
public function referToFieldInClassA() {
System.out.println(A.a);
}
}
Is there anything in the Java reflection APIs to allow me to find all places where a particular field is referenced? What I'm looking for is a way to find out that (given the example) class B has a reference to A.a.
I know I can get all the Fields in a Class via the reflection API. But now I want to find all references to that Field.
Thanks.
From the standard APIs, I think the answer is no. Eclipse can do it, but that's not at runtime.
For an incredibly hack-ish way of doing it, get the ClassLoader object, get the resourceAsStream to get something, use something like JODE to decompile it, and parse the source from inside of the program.
But that's a crazy amount of work. What the heck are you using this for?
If your need is compile-time rather than run-time, and you don't have an IDE, the very old trick of changing the names of the fields and recompiling, and searching for what fails to compile. ;]
Then, of course, get yourself an IDE.
Related
A ClassName.class returns the Class object for that particular class. That said and understood, I can't really grasp what the keyword does when used directly in a method.., then, if we write class and follow it immediately with a dot, the list that appears seems to include all that's in scope there, i.e. local variables of the method, other methods and variables(depending on whether the method is static or not), method itself, and class itself..
Coming from its first stated function above, I find myself at odds with this one: I can't tell what it's exactly doing.. way I see it, it's the same word, expect same function at heart, but that doesn't seem to be the case here
Blurry.. I know, but any insight into it is appreciated. Thx.
I get similar behaviour from Netbeans:
However, these are somewhat bogus suggestions.
class.emptyList(), despite being a suggestion, will not compile. This is probably a peculiarity of the way suggestions are computed. If there's a way to get legal code out of these suggestions, I can't think of it.
Note that you get the same suggestions if you just hit CTRL+enter (or whatever keys you have bound to suggestions) on an empty statement.
Usually there are only two circumstances to use the word class:
When defining a class, for example public class MyClass { ... }
With a dot, after a class name, to get the Class object for a type - Class<Person> clazz = Nurse.class
Sometimes you feel you'd like to have a variable called class, but it's a reserved word, so you can't. It's quite common to see variables called clazz for that reason.
I need to have an app that during run-time can load another class and deserialize one of it's instance successfuly so that it can run it's methods and read the member variables.
From what I noticed, you can not serialize methods in Java, so I'm thinking about serializing the class instance in project2, load the compiled class with ClassLoader in project1, instantiate it and assign the deserialized instance from porject2 in project1 to the instantiated loaded class.
The serialized class will inherit the same parent class in both projects.
Is this the best way to go? It's a school project so the requirements are that my app can accept any other type of class without changing the code.
TL;DR: My plan is to load a compiled class with the ClassLoader so that my project knows about that class (specifically the methods inside) and then load that serialized class instance inside the project so that I can get the data from the instance and together with the loaded class (now I know the methods aswell), run the methods on the deserialized instance.
You are mistaken. The ability to call a method on some object isn't related to serialization at all.
What I mean: the method implementation is not part of the serialized data! Java serialization only writes field data into that output stream.
The implementation of a method only depends on the class file of some Java class. You can serialize and deserialize your objects as often as you want to - but what happens when you call a method on such an object is only determined by the class file that the corresponding class loader loaded for you when first accessing the corresponding class.
If your goal is really just about "one class dumps an object into a binary representation"; and another piece of code loads that binary data; turns it into an object; to access that object; then you do not need two projects. You also do not need to worry about "the methods being" there. As long as your ClassLoader knows the class of objects to be de-serialized, everything will just work. Just pick an example tutorial, like this here and work through it.
But: when your requirement is to invoke methods or access fields of arbitrary objects; then you don't look into serialization, but into Java reflection.
But a word of warning there: reflections sounds easy, but be assured: there are many many ways for you to write slightly wrong code. And because reflection is basically a runtime thing, the java compiler doesn't help much. You write code that looks reasonable, it compiles, you run it, and you get exceptions throw at you.
In that sense, reflection is an advanced topic in the Java curriculum; and I think you should rather step back and clarify with your teachers what exactly they expect from you.
Given your latest updates: then simply look into that tutorial about serialization (and forget about the reflection part). And to answer your question: yes, that sounds like a viable approach. Can't say more; as you are not sharing code so far.
I am using this code from an old IBM blog post about how to compile and use Java classes at runtime. The code mostly works great (and is quite well written, by the way), but unfortunately for me, it won't work in one of my use cases where the class being compiled refers to another class that can only be provided by the classLoader provided to the CharSequenceCompiler (from the blog post), not by the application classLoader.
To be more specific, The ClassLoader I pass into CharSequenceCompiler is a OSGi classLoader.
The bundle that owns this classLoader can find and return a class, say Foo.
class Foo { public static String FOO = "F"; }
I know this works if you do classLoader.findClass("Foo"); because when I call this from the debugger it works.
Now, from the class I compile at runtime, say Dynamic, I need to use Foo... so I pass the Foo bundle's ClassLoader to CharSequenceCompiler, then ask it to compile Dynamic:
class Dynamic { public static String D = Foo.FOO; }
This causes the following error:
error: cannot find symbol
Foo.FOO;
^
symbol: variable Foo
If Foo is in the same project as CharSequenceCompiler, then it works... so it's clearly a problem loading the class from the right class loader.
I have debugged this code for days (or evenings, tbh) and can't find out why the classLoader I provide to the compiler never even gets asked about this class...
The FileManager is asked to list() the resources in each package, but even when I use the debugger to manually add the FileObject to the returned list, it still won't work.
As the debugger cannot penetrate the native classes used by javac internally, I cannot progress anymore on this... does anyone have inside knowledge of the compiler that could explain what's going on?
I have figured this out after a long battle.
The problem with pretty much all implementations I found of in-memory java compilers based on the java.tools API is that, even though they let you pass in a ClassLoader to load the classes you compile, the classLoader is used only to load new classes, but not to obtain classes that can be used in the Java code being compiled.
For this reason, my use case (as explained in the question) would not work with the code shown in the IBM blog post (or with other projects like OpenHFT Java-Runtime-Compiler).
If you want the classes loaded by the ClassLoader you give to the compiler (which are not visible in the application ClassLoader) to be usable by the class being compiled, you need two things.
First, the ClassLoader classes must be enumerable. This can then be used by the JavaFileManager to implement the list() method properly. For each package, this method must return which classes the ClassLoader could load if required.
Secondly, you need to be able to build JavaFileObjects from the ClassLoader resources, because this is the type of the objects you must return. To do this, you need to ask the ClassLoader for the class's bytecode stream (use getResourceAsStream("Class.class")) and then just create a JavaFileObjectImpl. Basically, this in pseudo-code:
fileObject = new JavaFileObjectImpl( pathMinusDotClass, JavaFileObject.Kind.CLASS );
fileObject.openOutputStream()
.write( classLoader.getInputStream( path ) );
Now, the compiler will know which classes it can load from the provided classLoader and everything works.
I implemented this in a real compiler on my OSGiaaS project, which is not released yet but I plan to do it soon (writing in July 2016)... it includes a Java command in its shell which can run arbitrary Java code, and that's why I needed to get this working.
What is the benefits of using real java compiler. Isn't byte code generation option for you ?
In example: Byte Buddy or cglib
I'm currently working with the jodatime Java library and running into issues when trying to use it within coldfusion.
I've downloaded the latest jodatime 2.1 release, put the jar file into a folder on my local drive and pointed my coldfusion administrator to look at that folder in the ColdFusion Class Path under the Java and JVM settings page.
For the most part it works. but there are times when i get things like this:
local.oTestZone = createObject('java','org.joda.time.DateTimeZone').init('Europe/London');
Which should match with this: Constructor however I get an error in coldfusion saying:
Unable to find a constructor for class org.joda.time.DateTimeZone that accepts parameters of type ( java.lang.String ).
It works perfectly fine when I do something like this though:
local.oToZone = createObject('java','org.joda.time.DateTimeZone').forID('Europe/London');
Which matches on: forID
Am I missing something with my java implementation?
The DateTimeZone(String id) constructor is marked protected (it took me 3 reads of the JavaDoc to spot that), so CF won't be able to invoke it.
It looks to me like JodaTime expects you to use one of the static methods to construct your instances, so your second example is probably the right way of doing it.
You are dealing with an Abstract Class and a Protected Constructor.
A Protected Constructor means that only a subclass or a class in the same Package can call that constructor. So even though you are supplying the correct parameter, the constructor isn't available to your code.
The ColdFusion documentation has these tidbits:
"Although the cfobject tag loads the class, it does not create an instance object. Only static methods and fields are accessible immediately after the call to cfobject."
This is why forID works; it's a static method.
"To have persistent access to an object, you must use the init function, because it returns a reference to an instance of the object, and cfobject does not."
This and the previous statement are why methods like getOffset wont work in this situation.
I'm not familiar enough with this to know if there's a class that you can instantiate that will give you access to the constructor, but hopefully someone else can chime in.
Can a class add a method to itself at runtime (like from a static block), so that if someone is performing reflection on this class, they'll see the new method, even though it wasn't defined at compile time?
Background:
A framework I'm using expects Action classes to be defined that have a doAction(...) method, by convention. The framework inspects these classes at runtime to see what type of parameters are available in their doAction() method. For example: doAction(String a, Integer b)
I'd like each class to be able to programatically generate its doAction() method with various parameters, just-in-time when it is inspected. The body of the method can be empty.
It's not simple. Once a class is loaded by a classloader, there is no way to change the methods of loaded classes. When a class is requested, a classloader will load it and link it. And there is no way (with Java) to change the linked code or to add/remove methods.
The only trick that comes to my mind is playing with classloaders. If we delete a custom classloader, then the classes loaded by that classloader should be deleted or inaccessible too. The idea that comes to my mind is to
implement one custom classloader
load the dynamic class with that custom classloader
if we have an updated version of this class,
remove the custom classloader and
load the new version of this class with a new instance of the custom classloader
I leave that as food for thought, can't prove, if this leads to a solution or if we have pitfalls.
As a simple answer to the question: No, we can't change a loaded class like we can change the content of fields with reflection. (we can't add or remove fields too).
Andres_D is right, we can very well do so using custom class loading, here is a detailed guide on how to do this: http://www.javaworld.com/javaworld/jw-06-2006/jw-0612-dynamic.html?page=1
The article explains how to write dynamic Java code. It discusses runtime source code compilation, class reloading, and the use of the Proxy design pattern to make modifications to a dynamic class transparent to its caller.
In fact researcher in Austria have written a JVM that even allows reloading classes with different type hierarchies. They have achieved this by using existing thread save points to generate a complete 'side universe' of an object and all it's related references and referenced content and then once fully reshuffled with all required changes simply swap in all changed classes. [1] Here a link to their project http://ssw.jku.at/dcevm/ the oracle sponsorship certainly makes for interesting speculations on future plans.
Less intrusive changes to method bodies and fields are already possible in the standard java VM using the Hot Swap capabilities of the JPDA as introduced in Java 1.4:
docs.oracle.com/javase/1.4.2/docs/guide/jpda/enhancements.html#hotswap
I'm not sure whether it was the first one but this Sun employee's paper from 2001 appears to be one of the early proposals mentioning the capabilities of the HotSpot to Hot Swap. [2]
REFERENCE
[1] T. Würthinger, C. Wimmer, and L. Stadler, “Dynamic Code Evolution for Java,” presented at the 8th International Conference on the Principles and Practice of Programming in Java, Vienna, 2010.
[2] M. Dmitriev, “Towards flexible and safe technology for runtime evolution of java language applications,” in OOPSLA Workshop on Engineering Complex Object-Oriented Systems for Evolution, 2001.
I've never tried anything quite like that myself, but you should have a look at ASM, cglib, and Javassist.
No, that is not (easily) possible in Java.
It sounds like you are trying to use Java as if it is a dynamic programming language. For example, Ruby has open classes: you can add and remove methods from Ruby classes at runtime. In Ruby, you can also have a "method missing" method in your class, that will be called when you try to call a method that doesn't exist in the class. Such a thing also doesn't exist in Java.
There is a version of Ruby that runs on the JVM, JRuby, and it has to do very difficult tricks to make open classes work on the JVM.
You can have a doAction method which does whatever you would like the generated method to do. Is there a reason it needs to be generated or can it be dynamic?
It looks like there is no way to add method dynamically. But you can prepare an class with a list of Methods or an hash like:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
public class GenericClass {
private HashMap<String, Method> methodMap = new HashMap<String, Method>();
public Object call(String methodName,Object ...args)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method method = methodMap.get(methodName);
return method.invoke(null, args);
}
public void add(String name,Method method){
if(Modifier.isStatic(method.getModifiers()))
methodMap.put(name, method);
}
public static void main(String[] args) {
try {
GenericClass task = new GenericClass();
task.add("Name",Object.class.getMethod("Name", new Class<?>[0]));
} catch (NoSuchMethodException | SecurityException e) {
e.printStackTrace();
}
}
}
Than, using reflections you can set or unset the attribute.
I believe you need some byte code altering tool/framework, such as asm, cglib or javassist.
You can achieve this via aspects/weaving like it's done Spring, but I believe you still need to have the method defined first.
Proxy may help. But have to instantiate a Proxy every time you want to add or remove a method.
What I suggest should work for your situation:
1. You have an existing class MyClass with n methods
2. You want to include (n+1) th method which is not in the class while compiling in another .java source file
My way to solve it is Inheritance. Create a new .java source file for a Class MyClassPlusOne extending the first class MyClass. Compile this class and use the object. How can I compile and deploy a java class at runtime?
class MyClassPlusOne extends MyClass
{
void doAction(String a, Integer b)
{
int myNPlus1 = a+b;
//add whatever you want before compiling this code
}
}
I'm not sure that is possible. However, you could use AspectJ, ASM, etc. and weave these methods into the appropriate classes.
The other alternative is to use composition to wrap the target class and provide the doAction method. You would end up delegating to the target class in this case.
This is a rather old question, but I still found myself looking at it today so, just in case, I'll add my two cents.
If you are using Java 8+, you can define "default" implementations of an interface method, so you can just define the interface with all the extra methods with empty default implementations, and add the implements clause in the desired classes. This approach, in some cases, may be the easiest one.
If you don't have control over the definition of the classes, or you need compatibility with older Java versions, you can still define an interface containing all the required extra methods; but in this case, implement a "Decorator" class with a method that receives the object to "decorate" as parameter, and returns a DynamicProxy instance, wrapping the passed object with this interface.
If you are using Spring, the decorator can be added to the context as a #Component, so you can inject it wherever you need to use it. If any of the objects you need to inject are Spring Beans, you could implement a FactoryBean that uses the decorator to return the instances, so you can just forget about calling the decorator explicitly for them.