Getting method via reflection - java

My previous post was not very clear, sorry for that. I will try to give a better example of what I am trying to do.
I have an Java application that will load .class files and runs them in a special enviroment (the Java app has built-in functions) Note: This is not a library.
That Java application will then display an applet, and I want to modify the variables in the applet.
The main class of the applet is called 'client'.
The Java application will load the applet by creating an new instance of class 'client'.
I already got access to the 'client' class. the Java application will put the applet in a variable:
Applet client = (Applet) loadedClientClass.newInstance();
So I did this:
Class<?> class_client = client.getClass();
I can now read and set the fields but the 'client' class will call a funation of an other class, like this:
otherClass.someVoid(false);
And if I try something like:
class_client.getDeclaredMethod("otherClass.someVoid",boolean.class);
It will fail, saying that the function can not be found.
'otherClass' is the direct class name, it is not a reference to a new instance of the class as far as I know.
Is there any way to get 'otherClass.someVoid'?

You're using getDeclaredMethod like a static method (expecting it to return methods from any class), but it only returns method from the class itself. Here's how you can call otherClass.someVoid(false).
Class<?> otherClass = Class.forName("com.xyz.OtherClass"); // Get the class
Method method = otherClass.getDeclaredMethod("someVoid", boolean.class);
// If the method is an Class (ie static) method, invoke it on the Class:
method.invoke(otherClass, false);
// If the method is an instance (ie non-static) method, invoke it on an instance of the Class:
Object otherInstance = otherClass.newInstance(); // Get an instance of other class - this approach assumes there is a default constructor
method.invoke(otherInstance, false);

If the class isn't initialized, the var someInteger doesn't exist. It's a member variable, so it only exists inside of instances of the class. So, you can't change it since it's doesn't exist. Now, if you made it a static variable, then you could change it.

Is there any way to change 'otherClass.someInteger' through the
'mainClass' class?
No.
But you can get it via OtherClass' class via Class.forName:
Class<?> theOtherClazz = Class.forName("OtherClass");
And then get the methods via theOtherClazz.getDeclaredMethod

Related

How to pass PHP class as parameter to a builder function?

I implemented an object builder which takes a class name and tries to create a new instance object. The builder tries to inject services if any required. The class name is passed as a string in the current implementation. Here is an example
$className = '\Example\Application\ServiceClass';
$service = CiContext::newInstance($className);
However, this is not compatible with my IDE (eclipse) and the refactoring process does not find the class name (in the string form).
Is there any way to get the class name like java does?
Class classInstance = ServerClass.class;
In this case, the refactoring process finds the class reference and changes the class name.
Well, PHP7 class constant is supported on a class name. For example, the following code is correct in PHP 7.4:
$service = CiContext::newInstance(\Example\Application\ServiceClass::class);
This will solve my problem and the IDE find the class usage.
On the other hand, the class literal is going to support for objects too. For more information see class literal on object

Unable to correctly initialize xml-security library using ColdFusion 10.0

I am using the following to initialize in CF 10 and I placed the xmlsec-1.5.8.jar file under Coldfusion10/cfusion/lib
<cfset Init = CreateObject("Java", "org.apache.xml.security.Init.Init()")>
I have also tried placing the above code in a cfscript as
Init = CreateObject("Java", "org.apache.xml.security.Init.Init()");
I am getting the following error.
You must initialize the xml-security library correctly before you use it. Call the static method "org.apache.xml.security.Init.init();" to do that before you use any functionality from that library.
Thank you.
In addition to the syntax error, there is another problem. The error message is indicating you must call a static method of that class first. One that is literally named init(). The problem is init() has a special meaning in CF. CF does not allow using the new keyword with java objects. Instead, it uses the name init() as a pseudo-constructor, which allows you to create a new instance of a class. So when you do this:
obj = createObject("java", "org.apache.xml.security.Init").init();
CF will create a new instance of that class, NOT call a method named init(). AFAIK, the only way around it is to use reflection. Something along these lines:
// get a reference to the class
ref = createObject("java", "org.apache.xml.security.Init");
// initialize if needed
if (!ref.isInitialized()) {
// find static method named "init" with no parameters
method = ref.getClass().getDeclaredMethod("init", []);
// invoke it via reflection
method.invoke(ref, javacast("null", ""));
}
placed the xmlsec-1.5.8.jar file under Coldfusion10/cfusion/lib
While there is nothing wrong with doing that, as of CF10, you can also load jars dynamically via your Application settings, ie this.javaSettings. If the feature seems familiar, it is basically a rip of Mark Mandel's awesome JavaLoader.cfc, only baked into CF ;-)

How to get as a stream any class loaded from a jar not in the classpath?

I have a web-app which I want to work roughly as follows:
Someone uploads a jar (say myjar.jar) along with the name of class to analyze (say test.Test). The exact purpose of analysis is irrelevant so assume that the web-app does some static analysis on it.
I am able to upload the jar and load the class in Java using the hacks described here and here (MultiClassLoader).
If I know the methods inside the class, I can invoke them using reflection. Following assumes a method with signature foo(String)
Class c = jarLoader.loadClass("test.Test", true);
Object instance = c.newInstance();
Method foo = instance.getClass().getDeclaredMethod("foo", new Class[]{String.class});
// foo takes one para String
foo.setAccessible(true);
foo.invoke(instance, (Object) "hello");
Now, suppose, I need to find out what methods are there inside test.Test. To do this, I use the ASM framework, which needs the class as a stream. This is where I am running into a problem. I am unable to do getResourceAsStream or its equivalents. This is what I tried:
Type t = org.objectweb.asm.Type.getType(c); // uses asm library
String url = t.getInternalName() + ".class";
c.getClassLoader().getResourceAsStream(url); // gives null
Same problem if I use:
c.getClassLoader().getResourceAsStream(c.getSimpleName() + ".class");
etc.
What is the right way to get resource as stream, where the resource is a class file loaded from a jar NOT in the class path. Note that the entire thing is done via a web-app.
EDIT: Getting methods is just an example. What I really want is to get the class as a stream. I need to use ASM because it gives me other information (such as parameter names), which I cannot get via getDeclaredMethods or getMethods.
Re: "Now I need to find out what methods are there inside test.Test"
You get the class via Class c = jarLoader.loadClass("test.Test", true);. Class also has getDeclaredMethods() and getMethods().
EDIT: #Jus12, from your second link Java Tip 70: Create objects from jar files!:
protected byte[] loadClassBytes (String className)
ASM has a ClassReader(byte[] b) constructor.
You can use a URLClassLoader, which takes a List of URLs in its constructor. You can then load the class by invoking the loadClass method on the URLClassLoader instance to get the Class<?> object for the class that you are after. Once you have that, you can then use reflection to create instances, and/or get general information about the class.
I have not tried, but the URLClassLoader does also have a getResourceAsStream method.

Jython - Correct way of creating class instances & executing methods from Python class

I have a Python file which contains a class. I need to create an instance of that class and be able to call methods in that through Java.
I came up with a solution like this:
PythonInterpreter r = new PythonInterpreter();
r.execfile("File.py");
PyObject p = r.eval("Car().begin()");
System.out.println(p.toString());
And the python code:
class Car(SomeExtendedClass):
myvar = 5
def set(self, my):
self.myvar = my;
def begin(self):
return self.myvar
Now, when I execute this, it prints 5 But if I run the following code:
PyObject p = r.eval("Car().begin()");
System.out.println(p.toString());
r.eval("Car().set(7)");
p = r.eval("Car().begin()");
System.out.println(p.toString());
It will still print 5, instead of 7
It looks like I did not create one instance of Car and it always creating a new instance instead of using the created one.
Am I right?
Is it possible to create a new instance from a class in a Python file, and invoke/get data from methods with Java?
I have tried loading PyInstance using eval() but I get cannot cast exception from it:
return (PyInstance) this.interpreter.eval(className);
I just found out the solution for this "mystery"
At first, we want to execute the python file we're going to get instances from:
r.execfile("File.py");
And then define the PyObject which will contain the class that you want to invoke:
PyObject car = r.get("Car");
And then you have to call the __call__ method in order to create a new instance of Car, and cast it to PyObjectDerived:
PyObjectDerived p = (PyObjectDerived) o.__call__();
Now you can invoke methods, like this:
Python code:
def set(self, my):
self.myvar = my;
Your java call:
p.invoke("set", Py.newInteger(5));
Hope I helped anyone.
Whenever you call Car() you create a new instance of the class. So this create a new object and calls its set method:
r.eval("Car().set(7)");
But this then creates another instance rather than manipulating the existing one:
p = r.eval("Car().begin()");
The call to r.eval("Car().begin()"); creates a new python object as you require, but it actually returns a reference to the python object containing the return value from the begin() method - not to the instance created. This isn't what you wanted.
Leaving the python class exactly as defined, this code gets a reference to a single instance of the class:
PyObject p = r.eval("Car()");
(As you already saw, an alternative is to omit the parenthesis which gets you a reference to the python class object, and then using __call__ on it to create an instance).
Then to call the method on the existing instance:
p.invoke("set", Py.newInteger(7));
To get at the modified value, since it is an attribute of the instance and is not available via a 'getter' method, the getattr method of the PyObject class can get to it (or you could add a get method to the python code):
System.out.println(p.__getattr__("myvar"));
It's a shame that once you get a reference to the object via p you can't just call the method on it with java syntax, but of course Java knows nothing of the methods and/or attributes available on the Python object and even if it did they could change at any time because of the dynamic nature of Python. So you're left with methods like invoke to bind Java/Python together.

Is runtime-compiled-class instantiation & usage possible in Java without reflection?

I would like to know if there exists any kind of library or workaround to use my runtime compiled classes ( I dynamically generate my classes, writing .java, then compiling them in .class all of this happens at runtime) without using a reflection library?
Loading using reflection I always have to work like this:
//path where my newly generated classes are
File file = new File("e:\\tmp");
// Convert File to a URL
URL url = file.toURI().toURL();
URL[] urls = new URL[]{url};
ClassLoader cl = new URLClassLoader(urls);
Class cls = cl.loadClass("eu.dataaccess.footballpool.TGoal");
// Create an instance of the class just loaded
Object o = cls.newInstance();
Method method2 = cls.getDeclaredMethod("getIMinute");
Object result2 = method2.invoke(o);
My question is if it's somehow possible to use at runtime
TGoal x = new TGoal();
and
x.getIMinute();
EDIT: It seems it is impossible to act the way I hoped to. I modify my question so: is it possible to load a whole package at runtime, in a way that the classes of the loaded package are able to communicate each other without the method.invoke, meanwhile the main activation of the package is done with the method invoke() ?
I tried without any luck, i have some "error: cannot find symbol", it seems the runtime-loaded classes can't communicate each other
If you're not using the reflection api you have to instantiate classes via the new operator. This requires having the class file at compile time. So it is not possible. If your class TGoal is implementing an Interface IGoal, then you can cast your Object o to IGoal. This enables you to work with your Object like with any other object without using the reflection api.
You can do
x.getIMinute();
by using interfaces, but AFAIK you cannot create new class instances without reflection.
Instead, to call methods of your dynamically created objects, you
can declare an interface:
public interface MinuteGetter{
public int getIMinute();
}
Your dynamic objects have to implement his, than you can do:
Class cls = cl.loadClass("eu.dataaccess.footballpool.TGoal");
// Create an instance of the class just loaded
MinuteGetter o = (MinuteGetter) cls.newInstance();
o.getIMinute();
If applying an interface to your code is not an option for you, you can try to give a try to AnonymousClassLoader. See this detailed post about it.
It work only on Java 7, and please note that I never used it, so how don't know if it offer better performance than reflection.
Are you sure you have to create the Code at runtime? The easiest way is to avoid this.
If the TGoal x = new TGoal() doesn't have to happen in this program, then create a main function in the generated code and start a second java application.

Categories