Reflection: Instantiate All Classes in a Package?

J

Jason Cavett

I was wondering...

Is it possible, by using Java reflection, to instantiate all classes
existing in a package without knowing the names of those classes. I'm
envisioning something like this (pseudocode):

Start my class
Class goes to package x
Package x contanis all the classes I need to instantiate
Using a (loop/something?) I loop through all the classes and
instantiate each one

To clarify what I'm trying to do, I am creatnig an error checking
application that relies on a series of rules that groups of developers
will code in Java (yeah, I realize I could have it in XML or something
that makes more sense, but I am the third or fourth developer to work
on this project). All the (compiled) classes are placed in a specific
package, but I never will know exactly which classes are there. I was
hoping for some way to discover and initialize them at runtime. (They
all implement the same interface, so that part is easy.)

Is this even possible? Is there a better solution? Thanks for any
clarification.
 
J

Joshua Cranmer

Jason said:
I was wondering...

Is it possible, by using Java reflection, to instantiate all classes
existing in a package without knowing the names of those classes. I'm
envisioning something like this (pseudocode):

Start my class
Class goes to package x
Package x contanis all the classes I need to instantiate
Using a (loop/something?) I loop through all the classes and
instantiate each one

To clarify what I'm trying to do, I am creatnig an error checking
application that relies on a series of rules that groups of developers
will code in Java (yeah, I realize I could have it in XML or something
that makes more sense, but I am the third or fourth developer to work
on this project). All the (compiled) classes are placed in a specific
package, but I never will know exactly which classes are there. I was
hoping for some way to discover and initialize them at runtime. (They
all implement the same interface, so that part is easy.)

Is this even possible? Is there a better solution? Thanks for any
clarification.

Using Java reflection, the answer is NO. For more information, check the
message thread "Getting a list of classes in a package"; there is a nice
long discussion on class/package/reflection.

P.S. it generally helps to search recent posts on Usenet before asking a
question.
 
J

Jason Cavett

Using Java reflection, the answer is NO. For more information, check the
message thread "Getting a list of classes in a package"; there is a nice
long discussion on class/package/reflection.

P.S. it generally helps to search recent posts on Usenet before asking a
question.- Hide quoted text -

- Show quoted text -

My mistake. Thanks for pointing me to that thread.
 
O

Oliver Wong

Joshua Cranmer said:
Jason said:
I was wondering...

Is it possible, by using Java reflection, to instantiate all classes
existing in a package without knowing the names of those classes.
[...]

Using Java reflection, the answer is NO. For more information, check the
message thread "Getting a list of classes in a package"; there is a nice
long discussion on class/package/reflection.

Actually, the answer turned out to be "yes" (though I can't find the
thread where we concluded this), but you would probably never want to
instantiate all the classes existing in a package anyway, because there
are an infinite number of such classes.

OP, instead of instantiating all classes in a package, how about
instantiating all classes located within a specific directory on the local
harddrive?

- Oliver
 
O

Oliver Wong

Oliver Wong said:
Joshua Cranmer said:
Jason said:
I was wondering...

Is it possible, by using Java reflection, to instantiate all classes
existing in a package without knowing the names of those classes.
[...]

Using Java reflection, the answer is NO. For more information, check
the message thread "Getting a list of classes in a package"; there is a
nice long discussion on class/package/reflection.

Actually, the answer turned out to be "yes" (though I can't find the
thread where we concluded this),

Found it:
http://groups.google.ca/group/comp...._frm/thread/4017ee8e8edf3690/e7ca74ec29d74031

- Oliver
 
M

Mark Rafn

Is it possible, by using Java reflection, to instantiate all classes
existing in a package without knowing the names of those classes.
[...]
Using Java reflection, the answer is NO. For more information, check the
message thread "Getting a list of classes in a package"; there is a nice
long discussion on class/package/reflection.

Oliver Wong said:
Actually, the answer turned out to be "yes" (though I can't find the
thread where we concluded this)

Um, no. The answer turned out to be "No, but if you define your problem more
clearly, we can suggest alternatatives that are possible, like enumerating
classes in certain known locations and instantiating those that implement a
given interface."
OP, instead of instantiating all classes in a package, how about
instantiating all classes located within a specific directory on the local
harddrive?

Indeed!
 
C

Chris Uppal

Mark said:
Um, no. The answer turned out to be "No"

No, /that/ conversation concluded -- correctly -- that the answer is "yes".
It is trivial, albeit a little slow, to probe a classloader for all the
possible potential names of classes -- see the link in Oliver's follow-up post
for details and further speculation.

-- chris
 
J

Joshua Cranmer

Chris said:
No, /that/ conversation concluded -- correctly -- that the answer is "yes".
It is trivial, albeit a little slow, to probe a classloader for all the
possible potential names of classes -- see the link in Oliver's follow-up post
for details and further speculation.

-- chris

When I said that the answer is "no", I meant that purely using
reflection, i.e. stock java.lang.reflect.*/ClassLoader, this could not
be done. Through writing custom ClassLoaders or (my preference), parsing
the class path/bootstrap path/extensions directory, one can obtain the
needed classes.

The OP originally asked for the answer using /reflection/ -- he was more
or less asking if the answer could there was a method along the lines of
getAllClasses(String package).

In summary: Yes, one can get a list of classes in a certain package
through various means, but no, it cannot be done through /pure/
reflection. Happy now?
 
C

Chris Uppal

Joshua said:
In summary: Yes, one can get a list of classes in a certain package
through various means, but no, it cannot be done through /pure/
reflection. Happy now?

No, It can be done through nothing more than pure reflection (using only
ClassLoader.findClass() as exposed via Class.forName(String, ClassLoader))
Read the thread that Olver referenced. I was going to post code but, what with
the difficulties of handling Unicode in Java, and the absence of standard
combinatorial generators in the library, it's a bit more effort to do properly
than it's worth.

-- chris
 
J

Joshua Cranmer

Chris said:
No, It can be done through nothing more than pure reflection (using only
ClassLoader.findClass() as exposed via Class.forName(String, ClassLoader))
Read the thread that Olver referenced. I was going to post code but, what with
the difficulties of handling Unicode in Java, and the absence of standard
combinatorial generators in the library, it's a bit more effort to do properly
than it's worth.

-- chris

Should I append 'feasibly' to my list? To use ClassLoader.findClass()
would require checking more than 64K^64K ~ 10^1M combinations to find
every class and probably on the order of 10^22 for more reasonable
assumptions (100 possible characters, 20-character lengths). It would be
much more efficient to open the Jar-files, find the package directory,
and load the classes.
 
C

Chris Uppal

Should I append 'feasibly' to my list?

Please feel free ;-)

To use ClassLoader.findClass()
would require checking more than 64K^64K ~ 10^1M combinations to find
every class

I did warn that the technique was a little slow...

-- chris
 
J

Jason Cavett

Is it possible, by using Java reflection, to instantiate all classes
existing in a package without knowing the names of those classes. [...]
Using Java reflection, the answer is NO. For more information, check the
message thread "Getting a list of classes in a package"; there is a nice
long discussion on class/package/reflection.
Oliver Wong said:
Actually, the answer turned out to be "yes" (though I can't find the
thread where we concluded this)

Um, no. The answer turned out to be "No, but if you define your problem more
clearly, we can suggest alternatatives that are possible, like enumerating
classes in certain known locations and instantiating those that implement a
given interface."
OP, instead of instantiating all classes in a package, how about
instantiating all classes located within a specific directory on the local
harddrive?

Indeed!
Um, no. The answer turned out to be "No, but if you define your problem more
clearly, we can suggest alternatatives that are possible, like enumerating
classes in certain known locations and instantiating those that implement a
given interface."

Sorry...I've been away for a bit.

Each class will implement the same interface.
Each class will exist in the same package.

I want a way (without knowing the actual names of the classes in
package X) to instantiate those classes. This way, developers can
continuously add new rules (errors and warnings) and the JAR can
easily be redistributed just by packaging it up and pushing it out to
the main system.

Any additional suggestions on how to do this?

P.S. Another alternative I thought of is have some sort of
configuration file where a developer adds the name of his class to the
config file every time he adds a new class. The major problem with
this is, 1, it will have to be read every time the error checker is
run and, 2, it is prone to error if a developer types the class name
incorrectly.

Thanks
 
A

Andrew Thompson

I want a way (without knowing the actual names of the classes in
package X) to instantiate those classes. This way, developers can
continuously add new rules (errors and warnings) and the JAR can
easily be redistributed just by packaging it up and pushing it out to
the main system.

1) Menu item (button or D'n'D funtionality) to
'add new rules archive'. Once the app. knows
of the jar..
2) Copy the jar to a known location,
3) Iterate the ZipEntry's looking for classes
in the right package,
4) do the biz to determine if they implement
the interface, then..
5) add them to a single list of class names
that can be serialised for later loading.

(That's how I would approach it, failing
better suggestions from the design gurus.)

Andrew T.
 
O

Oliver Wong

Joshua Cranmer said:
It would be much more efficient to open the Jar-files, find the package
directory, and load the classes.

It sounds like you haven't read the thread that I linked to. I don't
know why you might want to avoid reading that thread, but this post will
mainly be a regurgitation of what was written in that thread, since I'm
assuming you haven't read it. Your solution does not solve the problem
that the OP originally *stated* (though it probably solves the problem
that the OP originally *intended*).

There is not a one-to-one correspondence between packages and
directories on computers. So for example, if you were using the "scan
directories" approach and were interested in all classes in package "foo",
it is not sufficient to merely scan directories named "foo" on your
computer. You'd also have to scan directories named "foo" on my computer,
and on computers which I may have thrown into black holes. (This is where
we initially, and incorrectly, concluded that it was completely
impossible).

Later, it was decided that two classes are the same if they have the
same bytecode, even if they reside on different computers. E.g. if I write
a class on a computer, and then throw that computer into a black hole, and
you also write a class, and that class has the same bytecode as the class
that I wrote, then they are by definition the same class. (This is
philosophically comparable to the idea that if I write "3" on a piece of
paper, and you write "3" on a different piece of paper, we are both wrote
down the same number, the number itself being an abstract concept which is
not directly associated to either of our pieces of paper.)

So one could write an iterator which returns every possible sequence
bytecode, much like you can iterate through every possible integer, and
turn the bytecode sequence into a Java class. Some of these bytecode
sequences might declare names that conflict with each other (e.g. there's
more than one class in package "foo" with the name "Bar", but they are
distinct classes, having different bytecode), and so you'd need to
separate these classes into different classloaders.

Note that classes may "exist" in the "foo" package, even if they are
not stored on any local harddrive. This is philosophically comparable to
the idea that numbers "exists", conceptually, even if no one has ever
bothered to write them down yet.

This is also why I suspect that the OP doesn't really want to load all
classes from a given package, but instead, wants to load all classes
located in a given local directory (perhaps with certain additional
conditions).

- Oliver
 
M

Mark Thornton

Oliver said:
This is also why I suspect that the OP doesn't really want to load all
classes from a given package, but instead, wants to load all classes
located in a given local directory (perhaps with certain additional
conditions).

In which case you shouldn't add such a method to ClassLoader (because
not all class loaders can reasonably implement the method), but rather
to some sub class of ClassLoader (or an interface which ClassLoaders
might optionally implement).
Alternatively if you do put the method on ClassLoader you have to
document that implementation is optional or might only return classes
that had already been loaded. Perhaps add another method which returned
a value specifying the degree of enumeration that was possible.

Mark Thornton
 
W

Wojtek

Jason Cavett wrote :
They all implement the same interface, so that part is easy.

Even if they implement the same interface does not guarantee that they
have a constructor which you can easily use. If the class does not have
a parameter-less constructor, then you need to do some creative work to
find all the primitives/classes which the available constructors do
use.

And of course if those class's constructors need parameters....
 
M

Mark Rafn

Jason Cavett said:
Each class will implement the same interface.
Each class will exist in the same package.

As stated, it's impossible. s/package/searchable location/ and you're golden.
I want a way (without knowing the actual names of the classes in
package X) to instantiate those classes. This way, developers can
continuously add new rules (errors and warnings) and the JAR can
easily be redistributed just by packaging it up and pushing it out to
the main system.

Great. A jar is a searchable location. It's nearly trivial to list all
class files in a given subdirectory of a jar, and you don't even need
reflection to access them.
Use the java.util.jar.JarFile#entries method to list files in the jar,
translate them to classnames, and call
Class.forName(className).isAssignableTo(yourInterface)
to see if it's the right interface.
Any additional suggestions on how to do this?

The above is very easy to write.
P.S. Another alternative I thought of is have some sort of
configuration file where a developer adds the name of his class to the
config file every time he adds a new class. The major problem with
this is, 1, it will have to be read every time the error checker is
run and, 2, it is prone to error if a developer types the class name
incorrectly.

The config file will be faster than scanning the jar, and is a much more
direct reflection of developer intent than trying to discover things by magic.
It also allows the implementation to be in a different jar (or non-jar
classpath location) and still be found by your app.

I'd HIGHLY recommend using the config file.
 
D

Daniel Pitts

As stated, it's impossible. s/package/searchable location/ and you're golden.


Great. A jar is a searchable location. It's nearly trivial to list all
class files in a given subdirectory of a jar, and you don't even need
reflection to access them.
Use the java.util.jar.JarFile#entries method to list files in the jar,
translate them to classnames, and call
Class.forName(className).isAssignableTo(yourInterface)
to see if it's the right interface.


The above is very easy to write.


The config file will be faster than scanning the jar, and is a much more
direct reflection of developer intent than trying to discover things by magic.
It also allows the implementation to be in a different jar (or non-jar
classpath location) and still be found by your app.

I'd HIGHLY recommend using the config file.
Indeed. This is called Inversion of Control, and is a great boon to
complex, extensible designs.
Spring Framework does this quite well, with a intuitive XML
configuration.
 
J

Jason Cavett

Indeed. This is called Inversion of Control, and is a great boon to
complex, extensible designs.
Spring Framework does this quite well, with a intuitive XML
configuration.- Hide quoted text -

- Show quoted text -

Okay, thank you both, Mark and Daniel (and others). I guess I always
got the impression through schooling/reading/whatever that a config
file in this type of situation would *not* be a good thing (not even
sure why I thought that). Glad to hear otherwise - especailly because
it seems like such a good and simple solution.

Thanks again.
 

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

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top