Reflection: discovering the implementations of an interface

Z

z-man

Hello

What's the smoother way to discover via reflection all the classes
implementing a specific interface inside a package?

Example:

package com.acme.mypackage
{
MyInterface.class
Class1.class implements MyInterface
Class2.class
Class3.class
Class4.class implements MyInterface
Class5.class implements MyInterface
}

I want to retrieve Class1, Class4 and Class5.

Many thanks.
 
T

Thomas Weidenfeller

z-man said:
What's the smoother way to discover via reflection all the classes
implementing a specific interface inside a package?

This has been discussed a thousand times here. There is no general solution.

Please read an archive of this group.

/Thomas
 
A

Andrew Thompson

z-man wrote:
.....
What's the smoother way to discover via reflection ...

'hackich' or 'second hand' or 'cobbled together' are words
or phrases I might expect to hear in sentences that also
have the word 'reflection' in them - 'smoother' came as quite
a shock!

(and I see Thomas has already addressed the technical
points, so I won't revisit them..)

Andrew T.
 
Z

z-man

z-man wrote:
....

'hackich' or 'second hand' or 'cobbled together' are words
or phrases I might expect to hear in sentences that also
have the word 'reflection' in them - 'smoother' came as quite
a shock!

???

I can't grasp the tone of what you're saying, Andrew...

I think that Java core reflection implementation is quite incomplete;
otherwise, there wouldn't have been so many requests of such a
functionality over time (as Thomas says: "This has been discussed a
THOUSAND times here. There is no general solution.").

Using Mono, I found that .NET reflection implementation is much more
consistent and... smoother (are you shocked?).

Why hasn't Sun addressed this need till now?

Would it be so hard to release an official reflection class that
transparently discovers all the *available* classes from a specific package?
 
C

Chris Uppal

z-man said:
Would it be so hard to release an official reflection class that
transparently discovers all the *available* classes from a specific
package?

You concept of "package" is at fault. That's to say: you have a mental
"picture" of what they are and how they work which is only approximately
connected with reality.

I could trivially create a "package" which generated random new classes every
10 seconds for as long as the application is running. I could trivially create
a classloader which /always/ found a class for any possible classname it was
asked for -- again generating classes on the fly (and probably randomly). In
either case your question has no meaning at all.

If you want to restrict yourself to less dynamic ideas of what a package is,
and what sorts of classloader you are going to use, then the question may
become feasible to answer -- for instance, you could simply include a list of
classes (maybe indexed by interfaces) as a readable text resource in the same
JAR. Alternatively, you could discover the location from which the classloader
was loading .class files (if there was any concept of "location") and use
location-specific code to discover what .class files are available there. E.g.
reading the table-of-contents of a JAR file considered as a ZIP file, or
listing (recursively) the contents of a directory. Note that this may not be
possible; for instance if the "location" is an HTTP base-URL.

-- chris
 
Z

z-man

You concept of "package" is at fault. That's to say: you have a mental
"picture" of what they are and how they work which is only approximately
connected with reality.

I could trivially create a "package" which generated random new classes every
10 seconds for as long as the application is running. I could trivially create
a classloader which /always/ found a class for any possible classname it was
asked for -- again generating classes on the fly (and probably randomly). In
either case your question has no meaning at all.

Why? As the JVM loads such dynamic classes, couldn't it keep track of
their in-memory presence for on-the-fly reflection-at-package-level
purposes?

As I said, I intended to discover "all the *available* classes from a
specific package": AVAILABLE doesn't mean POSSIBLE. It's self-evident
that I didn't want to discover the whole universe of the possible
imaginative package: I simply did NOT want that. I wanted all the
reachable classes from a specific package within the classpath scope: is
it SO insane?

In fact, as the context of my question should have implied, I was
referring to the most common, real-life case: non-dynamically-generated
classes. *Possible* doesn't mean *practical*: I think that the typical
scenario is NOT randomly-generated classes, but well-established,
non-volatile classes.
If you want to restrict yourself to less dynamic ideas of what a package is,

YOU are restricting yourself to the limits of a platform.
and what sorts of classloader you are going to use, then the question may
become feasible to answer -- for instance, you could simply include a list of
classes (maybe indexed by interfaces) as a readable text resource in the same
JAR.
Awkward.

Alternatively, you could discover the location from which the classloader
was loading .class files (if there was any concept of "location") and use
location-specific code to discover what .class files are available there. E.g.
reading the table-of-contents of a JAR file considered as a ZIP file, or
listing (recursively) the contents of a directory. Note that this may not be
possible; for instance if the "location" is an HTTP base-URL.

OK.

As many people have asked for such a functionality, maybe just ignoring
the problem (as no official practise seems to exist) is somewhat an
exercise for snob theorists. ;-)
 
P

Piotr Kobzda

z-man said:
What's the smoother way to discover via reflection all the classes
implementing a specific interface inside a package?

Not necessarily smoother but possibly most accurate way to achieve that
is to instrument your program with you own agent (see
java.lang.instrument package specifications on how to do that), and than
having Instrumentation instance (passed to the agent's premain() by the
JVM) filter the results of getAllLoadedClasses() call on that instance.


piotr
 
Z

z-man

Not necessarily smoother but possibly most accurate way to achieve that
is to instrument your program with you own agent (see
java.lang.instrument package specifications on how to do that), and than
having Instrumentation instance (passed to the agent's premain() by the
JVM) filter the results of getAllLoadedClasses() call on that instance.

Really interesting.

This way it should be possible to retrieve dynamically-generated classes
too, shouldn't it?

Many thanks, Piotr!
 
L

Lothar Kimmeringer

z-man said:
As many people have asked for such a functionality, maybe just ignoring
the problem (as no official practise seems to exist) is somewhat an
exercise for snob theorists. ;-)

Fot this the most easy way is to implement your own ClassLoader
that is used at the beginning of your application that is
collecting this kind of information within a map you can access
without the need of Reflection (at the point of time you need it).
Of course this adds more overhead to the loading of classes, but
that's something you have to accept in your special case. No
need to slow down all the other applications (I assume about
99.999%) that doesn't.

Easy (just a method-call), smooth (fast, reliable) and also
cool (adding ClassLoaders) with so little effort. SUN thought
of everything ;-)

Your attempt of using Reflection for this kind of thing is
simply the wrong one, so there is no need to start a discussion,
why something like Mono (AKA .NET) or any other system that
has been created many years after Java, has got some specific
feature, Java doesn't.


Regards, Lothar
--
Lothar Kimmeringer E-Mail: (e-mail address removed)
PGP-encrypted mails preferred (Key-ID: 0x8BC3CD81)

Always remember: The answer is forty-two, there can only be wrong
questions!
 
P

Piotr Kobzda

z-man said:
This way it should be possible to retrieve dynamically-generated classes
too, shouldn't it?

Of course, it should.

See the output of running the following agent:


import java.lang.instrument.Instrumentation;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;

/**
* After building agent's jar with duly manifest run it with:
* java -javaagent:agent.jar ClassesAgent
*
* @author pk
*/
public class ClassesAgent {

private static Instrumentation inst;

public static void premain(String agentArgs, Instrumentation inst) {
ClassesAgent.inst = inst;
}

public static Class[] getAllClassesAssignableFrom(Class...
interfaces) {
ArrayList<Class> found = new ArrayList<Class>();
loop: for (Class c : inst.getAllLoadedClasses()) {
for (Class<?> ic : interfaces)
if (!ic.isAssignableFrom(c))
continue loop;
found.add(c);
}
return found.toArray(new Class[found.size()]);
}


interface Test {}

public static void main(String[] args) throws Exception {
System.out.println("lookup of classes implementing " +
Test.class + "...");
Class[] classes;
classes = getAllClassesAssignableFrom(Test.class);
System.out.println("classes found: " + Arrays.toString(classes));
Class tic = Proxy.getProxyClass(
Test.class.getClassLoader(), Test.class);
System.out.println("just generated: " + tic);
classes = getAllClassesAssignableFrom(Test.class);
System.out.println("classes found: " + Arrays.toString(classes));
}

}


piotr
 
C

Chris Uppal

z-man said:
Why? As the JVM loads such dynamic classes, couldn't it keep track of
their in-memory presence for on-the-fly reflection-at-package-level
purposes?

Of course it could. It does so internally. But why /should/ it ? All that
would happen is that people would misuse it[*]: the collection of classes which
/have/ been loaded is not the same as the collection of classes which are
/available/ to be loaded (even in a completely static situation).

If you need that functionality (but what for ??) then it's simple to add it.
If you need to be able to ask what classes /could/ be loaded then there is no
general solution -- so you should expect to be forced to create special-purpose
code to handle your own specific situation, taking advantage of whatever
situation-specific factors you can.

-- chris

([*] Maybe /you/ wouldn't misuse it, but the majority of the people who ask
this, or closely related questions, here would)
 

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,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top