empty interfaces via reflection

D

Daniel Pitts

Aryeh said:
Then how do you handle the return type?!?!?!? Namely I can't do:
Class<?> testClass = loadTestClass();
Object testInstance = testClass.newInstance();
Result res=new Result();
for (Method method: testClass.getDeclaredMethods())
res.merge((Result) method.invoke(testInstance, new
Object[0])); // cast exception
The reason why it is not possible is any Result object created by a
test is <MyClassLoader>.Result and all the results here are
<SystemClassLoader>.Result
Looking back at an earlier post, your custom MyClassLoader goes like this:
A custom ClassLoader is expected to override findClass(String) rather
than loadClass(String), as the latter (indirectly) accomplishes this
behaviour:

"When requested to find a class or resource, a ClassLoader instance will
delegate the search for the class or resource to its parent class loader
before attempting to find the class or resource itself."
MyClassLoader is loading Result instead of delegating to its parent
first, which should always find it first.

I just tested:import java.io.*;
import java.lang.reflect.*;

public class MyClassLoader extends ClassLoader
{
public Class findClass(String name)
{
try {
//if(name.startsWith("java."))
// return super.loadClass(name);

FileInputStream fis=new FileInputStream(name
+".class");
byte[] b=new byte[fis.available()];

fis.read(b);
fis.close();

return defineClass(name,b,0,b.length);
} catch(Throwable e) {
e.printStackTrace();
}

return null;

}

and now the class loader no longer honors recompiled classes:

Script started on Sun Oct 14 15:09:05 2007
jtest@monster:/home/jtest% java Main
1
^Z
Suspended
jtest@monster:/home/jtest% cat foo
import java.lang.reflect.*;

public class MyClass
{
public MyClass()
{
ack=new Integer(2);
}

public Integer getAck()
{
return ack;
}

private int foo;
private Integer ack;}

jtest@monster:/home/jtest% cp foo MyClass.java
jtest@monster:/home/jtest% javac MyClass.java
jtest@monster:/home/jtest% fg
java Main

1
^C
jtest@monster:/home/jtest% exit
Script ends on Sun Oct 14 15:09:45 2007

Just for ref here is the new main():

public class Main
{
public static void main(String[] args)
throws Throwable
{
while(true) {
ClassLoader loader=new MyClassLoader();
Class klass=loader.loadClass("MyClass");

MyClass m=(MyClass) klass.newInstance();

System.out.println(m.getAck());
System.in.read();
}
}

}

You should simply use UrlClassLoader and have the system classpath not
include your code that needs to be reloaded, and the URLClassLoader
have the path that DOES need to be reloaded (creating a new instance
of that class loader every time you need to reload the class)

That way, Result will be properly loaded by the System class loader,
and your reloadable class wont.

Hoep this helps,
Daniel.
 
A

Aryeh M. Friedman

Class<?> testClass = loadTestClass();
Object testInstance = testClass.newInstance();

...and you don't actually refer to MyClass. So, as long as MyClass is
not in the program's classpath, the system classloader won't load it;
but your custom classloader will, if it looks in the right directory.

Had other things to do so sorry for not trying this sooner but the
following test code (using findClass not loadClass as the override
method) still doesn't work:

public static void main(String[] args)
throws Throwable
{
while(true) {
ClassLoader loader=new MyClassLoader();
Class klass=loader.loadClass("MyClass");
Object o=klass.newInstance();


System.out.println(o.getClass().getDeclaredMethod("getAck").invoke(o));
System.in.read();
}
}
 
A

Aryeh M. Friedman

I still can not really see any reason why not to use AspectJ.

Yes - you need to distribute the aspectrt.jar, but most Java apps
require some jars.

Yes - developers will need the AspectJ tools, but they also need
an editor, a Java compiler etc..

With AspectJ can you freely change the class of an instant? (assuming
that the class your moving to implements the same methods)
 
S

Steven Simpson

Aryeh said:
the
following test code (using findClass not loadClass as the override
method) still doesn't work:

public static void main(String[] args)
throws Throwable
{
while(true) {
ClassLoader loader=new MyClassLoader();

I did get the following to work. It uses a URLClassLoader, as Daniel
Pitts suggested. Your MyClassLoader didn't seem to be doing anything
extra, so you may as well use the existing class - though I don't see
why yours wouldn't work.

You give the directory containing the class to be tested as the first
argument, and it is turned into a URL for the class loader. Make sure
this directory is not in your classpath.

import java.io.*;
import java.net.*;

public class Test {
public static void main(String[] args) throws Throwable {
File f = new File(args[0]);
URL[] path = new URL[] { f.toURI().toURL() };

while (true) {
ClassLoader loader = new URLClassLoader(path);
Class klass = loader.loadClass("SomeClass");
Object o = klass.newInstance();

System.out.println(o.getClass().getDeclaredMethod("getAck").
invoke(o));
System.in.read();
}
}
}
 
A

Aryeh M. Friedman

Aryeh said:
the
following test code (using findClass not loadClass as the override
method) still doesn't work:
public static void main(String[] args)
throws Throwable
{
while(true) {
ClassLoader loader=new MyClassLoader();

I did get the following to work. It uses a URLClassLoader, as Daniel
Pitts suggested. Your MyClassLoader didn't seem to be doing anything
extra, so you may as well use the existing class - though I don't see
why yours wouldn't work.

You give the directory containing the class to be tested as the first
argument, and it is turned into a URL for the class loader. Make sure
this directory is not in your classpath.

There is the rub... since it is meant for a standalone commercial app
I don't feel comfortable making any assumptions about the struct of
the user's class path (matter of fact on the surface I think all
loaded classes will have to be in the class path one way or an other
[cmd line arg passing maybe but not very portable])
 
L

Lew

Aryeh said:
With AspectJ can you freely change the class of an instant? (assuming
that the class your moving to implements the same methods)

Do you mean "change the class of an instance"?

No. At least not as I understand the question. AspectJ adds cross-cutting
concerns to the Java language; it doesn't change the semantics of the part
that it shares with the Java language itself. AFAIK.

Undoubtedly there is a different strategy (!) to achieve your real, and as yet
unstated, goal (!).

What exactly do you intend to accomplish with such an idiom?
 
D

Daniel Pitts

Sorry if this a double-post. Damn google.
Aryeh said:
the
following test code (using findClass not loadClass as the override
method) still doesn't work:
public static void main(String[] args)
throws Throwable
{
while(true) {
ClassLoader loader=new MyClassLoader();
I did get the following to work. It uses a URLClassLoader, as Daniel
Pitts suggested. Your MyClassLoader didn't seem to be doing anything
extra, so you may as well use the existing class - though I don't see
why yours wouldn't work.
You give the directory containing the class to be tested as the first
argument, and it is turned into a URL for the class loader. Make sure
this directory is not in your classpath.

There is the rub... since it is meant for a standalone commercial app
I don't feel comfortable making any assumptions about the struct of
the user's class path (matter of fact on the surface I think all
loaded classes will have to be in the class path one way or an other
[cmd line arg passing maybe but not very portable])

So, use it as an example, and work from there.
You can't do what you're trying to do without some assumptions about
the class path. Commercial products make assumptions all the time
(like, for instance, the validity of the environment their running
on). It is the only feasible way to do this. Just document the fact
that your program's execution environment should be *different* than
that of the tests. Or, figure out some other way of supporting that.
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

Aryeh said:
With AspectJ can you freely change the class of an instant? (assuming
that the class your moving to implements the same methods)

No.

But you can add functionality to an existing class without
changing its code.

Arne
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,139
Latest member
JamaalCald
Top