Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #31694 > unrolled thread

get a list of classes at runtime

Started byPhilipp Kraus <philipp.kraus@flashpixx.de>
First post2015-05-13 14:47 +0200
Last post2015-05-17 19:09 -0400
Articles 12 — 8 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  get a list of classes at runtime Philipp Kraus <philipp.kraus@flashpixx.de> - 2015-05-13 14:47 +0200
    Re: get a list of classes at runtime Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-05-13 10:06 -0400
      Re: get a list of classes at runtime Philipp Kraus <philipp.kraus@flashpixx.de> - 2015-05-13 16:14 +0200
        Re: get a list of classes at runtime Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-05-13 11:23 -0400
          Re: get a list of classes at runtime Arne Vajhøj <arne@vajhoej.dk> - 2015-05-17 19:29 -0400
        Re: get a list of classes at runtime Joshua Cranmer 🐧 <Pidgeot18@verizon.invalid> - 2015-05-13 22:15 -0500
      Re: get a list of classes at runtime e.d.programmer@gmail.com - 2015-05-13 08:59 -0700
        Re: get a list of classes at runtime Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-05-13 16:05 -0400
          Re: get a list of classes at runtime Martin Gregorie <martin@address-in-sig.invalid> - 2015-05-13 22:43 +0000
    Re: get a list of classes at runtime Joerg Meier <joergmmeier@arcor.de> - 2015-05-13 16:20 +0200
    Re: get a list of classes at runtime j4n bur53 <janburse@fastmail.fm> - 2015-05-13 17:47 +0200
    Re: get a list of classes at runtime Arne Vajhøj <arne@vajhoej.dk> - 2015-05-17 19:09 -0400

#31694 — get a list of classes at runtime

FromPhilipp Kraus <philipp.kraus@flashpixx.de>
Date2015-05-13 14:47 +0200
Subjectget a list of classes at runtime
Message-ID<mivd25$2m28$1@ariadne.rz.tu-clausthal.de>

[Multipart message — attachments visible in raw view] — view raw

Hello,

I would like to get a list of all loadable classes, because I create an 
UI which should be list on the user input, which classes are existst 
e.g. the user types ABC and I will get the full class name with 
packages, e.g. package1.subpackage.ABC and package2.ABC

I have taken a look into https://github.com/ronmamo/reflections but I 
don't find a call to filter all class names. How I can get the full 
class name list during runtime (all my classes are stored within a Jar 
file and the search should be also add the Java base classes e.g. 
String)

Thanks a lot

Phil

[toc] | [next] | [standalone]


#31695

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2015-05-13 10:06 -0400
Message-ID<mivlo4$83v$1@dont-email.me>
In reply to#31694
On 5/13/2015 8:47 AM, Philipp Kraus wrote:
> Hello,
>
>
> I would like to get a list of all loadable classes, because I create an
> UI which should be list on the user input, which classes are existst
> e.g. the user types ABC and I will get the full class name with
> packages, e.g. package1.subpackage.ABC and package2.ABC

     "All loadable classes" is a potentially infinite set, since a class
loader might look almost anywhere to find a class -- it might even
synthesize a class by filling a byte[] array with bytecodes and then
loading it.  But perhaps your goal is not quite so ambitious ...

> I have taken a look into https://github.com/ronmamo/reflections but I
> don't find a call to filter all class names. How I can get the full
> class name list during runtime (all my classes are stored within a Jar
> file and the search should be also add the Java base classes e.g. String)

     AFAIK, the JVM has no record of potentially loadable classes that
have not been loaded (there are probably some special-case exceptions
like String and Class and Throwable, but they'll all have been loaded
well before your code runs).  If I'm right, it means the only way you
can find the not-yet-loaded classes is to rummage through the JAR's (or
other sources) for yourself.  You presumably know where to find your
own JAR's and things; I believe all "base classes" reside in rt.jar.
I don't know of a convenient way to find "the" rt.jar that your JVM
happens to be using; the best I can think of is to read the java.home
System property and search from there. (Or from sun.boot.class.path,
but I'm not certain that's a property all JVM's will define.)

     Anyhow: Once you've found the JAR's, you'll read their directories,
do a little reformatting, and filter as you please.

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#31696

FromPhilipp Kraus <philipp.kraus@flashpixx.de>
Date2015-05-13 16:14 +0200
Message-ID<mivi58$2n3g$1@ariadne.rz.tu-clausthal.de>
In reply to#31695
On 2015-05-13 14:06:53 +0000, Eric Sosman said:

> On 5/13/2015 8:47 AM, Philipp Kraus wrote:
> 
>      AFAIK, the JVM has no record of potentially loadable classes that
> have not been loaded (there are probably some special-case exceptions
> like String and Class and Throwable, but they'll all have been loaded
> well before your code runs).  If I'm right, it means the only way you
> can find the not-yet-loaded classes is to rummage through the JAR's (or
> other sources) for yourself.  You presumably know where to find your
> own JAR's and things; I believe all "base classes" reside in rt.jar.
> I don't know of a convenient way to find "the" rt.jar that your JVM
> happens to be using; the best I can think of is to read the java.home
> System property and search from there. (Or from sun.boot.class.path,
> but I'm not certain that's a property all JVM's will define.)
> 
>      Anyhow: Once you've found the JAR's, you'll read their directories,
> do a little reformatting, and filter as you please.

I think so, but how do IDEs like IntelliJ or Eclipse this call? If I 
write into the code editor
something a dialog is show, which lists all possibility classes.
So imho I need to run over the Jar, create an index of all class files 
and use a pattern structure to
match the names.

Phil

[toc] | [prev] | [next] | [standalone]


#31698

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2015-05-13 11:23 -0400
Message-ID<mivq6r$ptd$1@dont-email.me>
In reply to#31696
On 5/13/2015 10:14 AM, Philipp Kraus wrote:
> On 2015-05-13 14:06:53 +0000, Eric Sosman said:
>
>> On 5/13/2015 8:47 AM, Philipp Kraus wrote:
>>
>>      AFAIK, the JVM has no record of potentially loadable classes that
>> have not been loaded (there are probably some special-case exceptions
>> like String and Class and Throwable, but they'll all have been loaded
>> well before your code runs).  If I'm right, it means the only way you
>> can find the not-yet-loaded classes is to rummage through the JAR's (or
>> other sources) for yourself.  You presumably know where to find your
>> own JAR's and things; I believe all "base classes" reside in rt.jar.
>> I don't know of a convenient way to find "the" rt.jar that your JVM
>> happens to be using; the best I can think of is to read the java.home
>> System property and search from there. (Or from sun.boot.class.path,
>> but I'm not certain that's a property all JVM's will define.)
>>
>>      Anyhow: Once you've found the JAR's, you'll read their directories,
>> do a little reformatting, and filter as you please.
>
> I think so, but how do IDEs like IntelliJ or Eclipse this call? If I
> write into the code editor
> something a dialog is show, which lists all possibility classes.
> So imho I need to run over the Jar, create an index of all class files
> and use a pattern structure to
> match the names.

     That's what I would do.  Note that a JAR will have directory entries
for *all* its classes, including nested classes, private classes, and
package-private classes.  You can filter out the nested classes by their
funny-looking names, but if you also want to filter based on access I
can think of only two ways:

     - Read the class file (the format is described in the JVM spec).

     - Load the class (use the three-argument form of Class.forName()
       if you don't want to initialize it) and use getModifiers().

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#31718

FromArne Vajhøj <arne@vajhoej.dk>
Date2015-05-17 19:29 -0400
Message-ID<55592458$0$292$14726298@news.sunsite.dk>
In reply to#31698
On 5/13/2015 11:23 AM, Eric Sosman wrote:
> On 5/13/2015 10:14 AM, Philipp Kraus wrote:
>> On 2015-05-13 14:06:53 +0000, Eric Sosman said:
>>> On 5/13/2015 8:47 AM, Philipp Kraus wrote:
>>>      AFAIK, the JVM has no record of potentially loadable classes that
>>> have not been loaded (there are probably some special-case exceptions
>>> like String and Class and Throwable, but they'll all have been loaded
>>> well before your code runs).  If I'm right, it means the only way you
>>> can find the not-yet-loaded classes is to rummage through the JAR's (or
>>> other sources) for yourself.  You presumably know where to find your
>>> own JAR's and things; I believe all "base classes" reside in rt.jar.
>>> I don't know of a convenient way to find "the" rt.jar that your JVM
>>> happens to be using; the best I can think of is to read the java.home
>>> System property and search from there. (Or from sun.boot.class.path,
>>> but I'm not certain that's a property all JVM's will define.)
>>>
>>>      Anyhow: Once you've found the JAR's, you'll read their directories,
>>> do a little reformatting, and filter as you please.
>>
>> I think so, but how do IDEs like IntelliJ or Eclipse this call? If I
>> write into the code editor
>> something a dialog is show, which lists all possibility classes.
>> So imho I need to run over the Jar, create an index of all class files
>> and use a pattern structure to
>> match the names.
>
>      That's what I would do.  Note that a JAR will have directory entries
> for *all* its classes, including nested classes, private classes, and
> package-private classes.  You can filter out the nested classes by their
> funny-looking names, but if you also want to filter based on access I
> can think of only two ways:
>
>      - Read the class file (the format is described in the JVM spec).

Or reuse that somebody else has read the class file format spec.

Aka using a byte code manipulation library.

Like BCEL or ASM.

>      - Load the class (use the three-argument form of Class.forName()
>        if you don't want to initialize it) and use getModifiers().

Arne

[toc] | [prev] | [next] | [standalone]


#31711

FromJoshua Cranmer 🐧 <Pidgeot18@verizon.invalid>
Date2015-05-13 22:15 -0500
Message-ID<mj13ug$epc$1@dont-email.me>
In reply to#31696
On 5/13/2015 9:14 AM, Philipp Kraus wrote:
> I think so, but how do IDEs like IntelliJ or Eclipse this call? If I
> write into the code editor
> something a dialog is show, which lists all possibility classes.
> So imho I need to run over the Jar, create an index of all class files
> and use a pattern structure to
> match the names.

For Eclipse at least, the location of used jar files (including the main 
rt.jar) is configured in the project settings. I recall Eclipse having 
settings to let you choose which of the available JDK/JREs to use. I 
imagine this is found in part by searching for well-known install 
locations, and letting a developer switch between multiple installed 
JDKs is useful for a Java IDE.

It is possible in a running Java program to find the directory of the 
current JRE (System.getProperty("java.home")), as well as the class path 
in use (System.getProperty("java.class.path")).


-- 
Beware of bugs in the above code; I have only proved it correct, not 
tried it. -- Donald E. Knuth

[toc] | [prev] | [next] | [standalone]


#31700

Frome.d.programmer@gmail.com
Date2015-05-13 08:59 -0700
Message-ID<4b9ec70b-28f1-488f-9945-ec6ebf8ebda8@googlegroups.com>
In reply to#31695
On Wednesday, May 13, 2015 at 10:07:19 AM UTC-4, Eric Sosman wrote:
> On 5/13/2015 8:47 AM, Philipp Kraus wrote:
> > Hello,
> >
> >
> > I would like to get a list of all loadable classes, because I create an
> > UI which should be list on the user input, which classes are existst
> > e.g. the user types ABC and I will get the full class name with
> > packages, e.g. package1.subpackage.ABC and package2.ABC
> 
>      "All loadable classes" is a potentially infinite set, since a class
> loader might look almost anywhere to find a class -- it might even
> synthesize a class by filling a byte[] array with bytecodes and then
> loading it.  But perhaps your goal is not quite so ambitious ...
> 
> > I have taken a look into https://github.com/ronmamo/reflections but I
> > don't find a call to filter all class names. How I can get the full
> > class name list during runtime (all my classes are stored within a Jar
> > file and the search should be also add the Java base classes e.g. String)
> 
>      AFAIK, the JVM has no record of potentially loadable classes that
> have not been loaded (there are probably some special-case exceptions
> like String and Class and Throwable, but they'll all have been loaded
> well before your code runs).  If I'm right, it means the only way you
> can find the not-yet-loaded classes is to rummage through the JAR's (or
> other sources) for yourself.  You presumably know where to find your
> own JAR's and things; I believe all "base classes" reside in rt.jar.
> I don't know of a convenient way to find "the" rt.jar that your JVM
> happens to be using; the best I can think of is to read the java.home
> System property and search from there. (Or from sun.boot.class.path,
> but I'm not certain that's a property all JVM's will define.)
> 
>      Anyhow: Once you've found the JAR's, you'll read their directories,
> do a little reformatting, and filter as you please.
> 
> -- 
> esosman@comcast-dot-net.invalid
> "Don't be afraid of work. Make work afraid of you." -- TLM

To find the rt.jar your IDE would just have to specify where the rt.jar is.
Normally to build a project in Eclipse you add "JRE System Library" to the build path.  You'll see that as a folder in the Package Explorer.  You can expand that folder.  I don't know if Oracle/Sun publishes a list of which jars to include or where they get it but my Eclipse project using Java 8 update 40 has 18 jars listed there.

[toc] | [prev] | [next] | [standalone]


#31702

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2015-05-13 16:05 -0400
Message-ID<mj0ao4$t8u$1@dont-email.me>
In reply to#31700
On 5/13/2015 11:59 AM, e.d.programmer@gmail.com wrote:
>[...]
> To find the rt.jar your IDE would just have to specify where the rt.jar is.
> Normally to build a project in Eclipse you add "JRE System Library" to the build path.  You'll see that as a folder in the Package Explorer.  You can expand that folder.  I don't know if Oracle/Sun publishes a list of which jars to include or where they get it but my Eclipse project using Java 8 update 40 has 18 jars listed there.

     I could be wrong, but I don't think that's the O.P.'s problem.
He wrote "I create an UI" that finds and lists classes (sounds like
a sort of auto-completion thing), in somewhat the manner of an IDE.
So I think the issue isn't "How do I tell my IDE where rt.jar is?"
but "How does a piece of executing code find the rt.jar its JVM is
using?"

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#31704

FromMartin Gregorie <martin@address-in-sig.invalid>
Date2015-05-13 22:43 +0000
Message-ID<mj0k1n$4rb$1@dont-email.me>
In reply to#31702
On Wed, 13 May 2015 16:05:17 -0400, Eric Sosman wrote:

> On 5/13/2015 11:59 AM, e.d.programmer@gmail.com wrote:
>>[...]
>> To find the rt.jar your IDE would just have to specify where the rt.jar
>> is.
>> Normally to build a project in Eclipse you add "JRE System Library" to
>> the build path.  You'll see that as a folder in the Package Explorer. 
>> You can expand that folder.  I don't know if Oracle/Sun publishes a
>> list of which jars to include or where they get it but my Eclipse
>> project using Java 8 update 40 has 18 jars listed there.
> 
>      I could be wrong, but I don't think that's the O.P.'s problem.
> He wrote "I create an UI" that finds and lists classes (sounds like a
> sort of auto-completion thing), in somewhat the manner of an IDE.
> So I think the issue isn't "How do I tell my IDE where rt.jar is?" but
> "How does a piece of executing code find the rt.jar its JVM is using?"

Since, IIRC, Eclipse is FOSS, I suppose the OP could always download its 
source and see how the class list is handled there.


-- 
martin@   | Martin Gregorie
gregorie. | Essex, UK
org       |

[toc] | [prev] | [next] | [standalone]


#31697

FromJoerg Meier <joergmmeier@arcor.de>
Date2015-05-13 16:20 +0200
Message-ID<1qnrqm0fz132l$.1tzazpkevh5wo.dlg@40tude.net>
In reply to#31694
On Wed, 13 May 2015 14:47:40 +0200, Philipp Kraus wrote:

> I would like to get a list of all loadable classes, because I create an 
> UI which should be list on the user input, which classes are existst 
> e.g. the user types ABC and I will get the full class name with 
> packages, e.g. package1.subpackage.ABC and package2.ABC

What you want is not quite possible. Since class loaders load on demand
(and some even from remote sources over the internet or out of a database),
there is no list of "possible loadable classes". You could write a loop
that attempts to load "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab" and so on, but that is unlikely to
produce an outcome you will be happy with.

Your question is akin to saying "I would like a list of all available
URLs". It just doesn't work like that.

There are of course many ways to get all loaded classes, but that again is
probably not what you want. Your best bet is something that scans all the
jars on the classpath, which will not give you an exhaustive list, but a
reasonable approximation.

This library may be helpful: <https://code.google.com/p/reflections/>

Spring also has something helpful:
<http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.html>

Good luck.

Liebe Gruesse,
		Joerg

-- 
Ich lese meine Emails nicht, replies to Email bleiben also leider
ungelesen.

[toc] | [prev] | [next] | [standalone]


#31699

Fromj4n bur53 <janburse@fastmail.fm>
Date2015-05-13 17:47 +0200
Message-ID<mivrmb$o2d$1@news.albasani.net>
In reply to#31694
Hi,

You can skim the class paths for entries of the
form *.class. A class path is either a directory
or an archive.

If its a directory, you have to recursively traverse
the directory. If its an archive you basically have
to read a zip file and skim its entries.

The most annoying thing is getting the class paths
in the first place.

Bye

Philipp Kraus schrieb:
> Hello,
>
>
> I would like to get a list of all loadable classes, because I create an
> UI which should be list on the user input, which classes are existst
> e.g. the user types ABC and I will get the full class name with
> packages, e.g. package1.subpackage.ABC and package2.ABC
>
>
> I have taken a look into https://github.com/ronmamo/reflections but I
> don't find a call to filter all class names. How I can get the full
> class name list during runtime (all my classes are stored within a Jar
> file and the search should be also add the Java base classes e.g. String)
>
>
> Thanks a lot
>
>
> Phil
>

[toc] | [prev] | [next] | [standalone]


#31717

FromArne Vajhøj <arne@vajhoej.dk>
Date2015-05-17 19:09 -0400
Message-ID<55591fc4$0$292$14726298@news.sunsite.dk>
In reply to#31694
On 5/13/2015 8:47 AM, Philipp Kraus wrote:
> I would like to get a list of all loadable classes, because I create an
> UI which should be list on the user input, which classes are existst
> e.g. the user types ABC and I will get the full class name with
> packages, e.g. package1.subpackage.ABC and package2.ABC
>
> I have taken a look into https://github.com/ronmamo/reflections but I
> don't find a call to filter all class names. How I can get the full
> class name list during runtime (all my classes are stored within a Jar
> file and the search should be also add the Java base classes e.g. String)

The general problem is difficult as described in several replies.

But assuming:
- only classes that can be loaded by class loader hierarchy for context
- only class loaders that are based on URLClassLoader
- only local directories and jar files
then it becomes a much simpler problem.

See below for inspiration.

Arne

====


import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class ClassFinder {
	private static final String CLASS_EXT = ".class";
	private static final String FILE_PROTOCOL = "file:/";
	private static String fileNameToClassName(String filename, String base) {
		if(filename.startsWith(base)) {
			return filename.substring(base.length() + 1, filename.length() - 
CLASS_EXT.length()).replace(File.separatorChar, '.');
		} else {
			throw new IllegalArgumentException("Filename not in base: " + filename);	
		}
	}
	private static void processDirectory(File f, List<String> res, String 
base) {
		for(File cf : f.listFiles()) {
			if(cf.isDirectory()) {
				processDirectory(cf, res, base);
			} else {
				String cfnam = cf.getAbsolutePath();
				if(cfnam.endsWith(CLASS_EXT)) {
					String clznam = fileNameToClassName(cfnam, base);
					res.add(clznam);
				}
			}
		}
	}
	private static void processJarFile(File f, List<String> res) throws 
IOException {
		try(JarFile jf = new JarFile(f.getAbsolutePath())) {
			Enumeration<JarEntry> jes = jf.entries();
			while(jes.hasMoreElements()) {
				JarEntry je = jes.nextElement();
				String jenam = je.getName();
				if(jenam.endsWith(CLASS_EXT)) {
					String clznam = jenam.substring(0, jenam.length() - 
CLASS_EXT.length()).replace('/',  '.');
					res.add(clznam);
				}
			}
		}
	}
	private static void processURL(URL url, List<String> res) throws 
IOException {
		if(url.getProtocol().equals("file")) {
			String path = URLDecoder.decode(url.toString(), 
"UTF-8").substring(FILE_PROTOCOL.length());
			File f = new File(path);
			if(f.isDirectory()) {
				processDirectory(f, res, f.getAbsolutePath());
			} else {
				processJarFile(f, res);
			}
		} else {
			throw new IllegalArgumentException("Unsupported protocol for URL: " + 
url.toString());
		}
	}
	private static void processClassLoader(ClassLoader cl, List<String> 
res) throws IOException {
		if(cl instanceof URLClassLoader) {
			URLClassLoader urlcl = (URLClassLoader)cl;
			for(URL url : urlcl.getURLs()) {
				processURL(url, res);
			}
		} else {
			throw new IllegalArgumentException("Unsupported ClassLoader: " + 
cl.getClass().getName());
		}
	}
	public static List<String> search() throws IOException {
		List<String> res = new ArrayList<String>();
		ClassLoader cl = ClassFinder.class.getClassLoader();
		while(cl != null) {
			processClassLoader(cl, res);
			cl = cl.getParent();
		}
		return res;
	}
	public static void main(String[] args) throws Exception {
		List<String> clzs = ClassFinder.search();
		for(String clz : clzs) {
			System.out.println(clz);
		}
	}
}




[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.java.programmer


csiph-web