Reflection: discovering the implementations of an interface

Discussion in 'Java' started by z-man, Oct 10, 2006.

  1. z-man

    z-man Guest

    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.
     
    z-man, Oct 10, 2006
    #1
    1. Advertising

  2. Thomas Weidenfeller, Oct 10, 2006
    #2
    1. Advertising

  3. 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.
     
    Andrew Thompson, Oct 10, 2006
    #3
  4. z-man

    z-man Guest

    On 10/10/2006 09:06 AM, Andrew Thompson wrote:
    > 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!


    ???

    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?
     
    z-man, Oct 10, 2006
    #4
  5. opalpa http://opalpa.info, Oct 10, 2006
    #5
  6. z-man

    Chris Uppal Guest

    z-man wrote:

    > 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
     
    Chris Uppal, Oct 10, 2006
    #6
  7. z-man

    z-man Guest

    z-man, Oct 10, 2006
    #7
  8. z-man

    z-man Guest

    On 10/10/2006 10:50 AM, Chris Uppal wrote:
    > z-man wrote:
    >
    >> 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.


    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. ;-)
     
    z-man, Oct 10, 2006
    #8
  9. z-man

    Piotr Kobzda Guest

    z-man wrote:

    > 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
     
    Piotr Kobzda, Oct 10, 2006
    #9
  10. z-man

    z-man Guest

    On 10/10/2006 02:19 PM, Piotr Kobzda wrote:
    > z-man wrote:
    >
    >> 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.


    Really interesting.

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

    Many thanks, Piotr!
     
    z-man, Oct 10, 2006
    #10
  11. opalpa http://opalpa.info, Oct 10, 2006
    #11
  12. z-man wrote:

    > 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:
    PGP-encrypted mails preferred (Key-ID: 0x8BC3CD81)

    Always remember: The answer is forty-two, there can only be wrong
    questions!
     
    Lothar Kimmeringer, Oct 10, 2006
    #12
  13. opalpa http://opalpa.info wrote:

    > http://forum.java.sun.com/thread.jspa?threadID=341935&start=15
    >
    > Note that list of classes implementing an interface can change while
    > program is executing.


    Note also, that Class.forName calls cinit.


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

    Always remember: The answer is forty-two, there can only be wrong
    questions!
     
    Lothar Kimmeringer, Oct 10, 2006
    #13
  14. z-man

    Piotr Kobzda Guest

    z-man wrote:

    > 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
     
    Piotr Kobzda, Oct 10, 2006
    #14
  15. z-man

    Piotr Kobzda Guest

    Lothar Kimmeringer wrote:

    > Note also, that Class.forName calls cinit.


    Class.forName(name, false, null) won't do that.


    piotr
     
    Piotr Kobzda, Oct 10, 2006
    #15
  16. z-man

    Chris Uppal Guest

    z-man wrote:

    > 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)
     
    Chris Uppal, Oct 11, 2006
    #16
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jeff 'Jones' Putz
    Replies:
    1
    Views:
    344
    John Saunders
    Nov 25, 2003
  2. Marcus Crafter
    Replies:
    1
    Views:
    353
    Mike Schilling
    Feb 19, 2004
  3. Sparko

    Interface implementations

    Sparko, Mar 2, 2004, in forum: Java
    Replies:
    4
    Views:
    358
    Christophe Vanfleteren
    Mar 2, 2004
  4. Chris
    Replies:
    2
    Views:
    319
    Chris
    Mar 15, 2007
  5. Replies:
    11
    Views:
    529
Loading...

Share This Page