URLClassloader loading class with unknown package name

C

Cory

I have a directory full of classes, all that implement a common
interface. All of the class files have different package names that I
do not know.

My question is, how do I call the URLClassLoader.loadClass() method to
instantiate a new instance if I don't know the package name?

ex: All I know is that the file's name is MyClass.class.

package com.hey.now;

public class MyClass implements someInterface {
....
}

I just want to say Object o =
(someInterface)myLoader.loadClass(myClass);

any ideas??

Thanks in advance!
 
D

David Zimmerman

Cory said:
I have a directory full of classes, all that implement a common
interface. All of the class files have different package names that I
do not know.

How can they be in different packages if they're in the same directory?
 
V

VK

Drop Java and migrate on C++

No package = no class
Moreover, package out of default classLoader = no package in most cases
 
M

Michiel Konstapel

Cory said:
I have a directory full of classes, all that implement a common
interface. All of the class files have different package names that I
do not know.

My question is, how do I call the URLClassLoader.loadClass() method to
instantiate a new instance if I don't know the package name?

ex: All I know is that the file's name is MyClass.class.

package com.hey.now;

public class MyClass implements someInterface {
...
}

I just want to say Object o =
(someInterface)myLoader.loadClass(myClass);

any ideas??

Thanks in advance!

Basically, if you don't know the package, you don't know the class name,
period. The package is an intrinsic part of the name. Now, you should be
able to parse the full name from the class file, perhaps using BCEL or by
looking at the bytes yourself. A standard URLClassLoader won't load them for
you, though, since it expects a class foo.bar.Baz in a directory structure
matching the package name: <base url>/foo/bar/Baz.class. A custom class
loader should do the job, though.
HTH,
Michiel
 
C

Cory

David Zimmerman said:
How can they be in different packages if they're in the same directory?

You can easily take a class file (someFile.class) out of a directory
and put it into another.... Is this what you mean?
 
C

Cory

VK said:
Drop Java and migrate on C++

No package = no class
Moreover, package out of default classLoader = no package in most cases


I don't think you understand my question. I have third party class
files that belong to certain third party packages. Here's an example
of the first class file:
---------------------------------

package com.hey.now;

public class MyClass implements someInterface {

public MyClass() {
System.out.println("Created a new MyClass object.");
}

public void init() {
System.out.println("Init called");
}
}
---------------------------------

Now in my code I want to be able to load this class and call init() on
the object. Here's the code I would use to do it if I knew the package
name for MyClass:

---------------------------------

private Class fileToClass(File file) throws IOException {
int magic = 0xCAFEBABE;
String name = file.getName();
Class retClass = null;

if(!file.exists() || !name.endsWith(".class")) {
return null;
}

DataInputStream dataIn = new DataInputStream(
new FileInputStream(file));
if(dataIn.readInt() == magic) {
//Now we know it's a Java CLASS file
URL[] url = new URL[1];
url[0] = file.toURL();

URLClassLoader urlLoader = new URLClassLoader(url);

try {
retClass = urlLoader.loadClass("com.hey.now.MyClass"));
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}

// TODO Auto-generated method stub
return retClass;
}
---------------------------------

Now the only thing I don't know is that 'com.hey.now' is the package
name for this class....

If you can load the class in some other way, I would love to know.

PS. Doing this in C++ would be murder
 
C

Cory

Michiel Konstapel said:
Basically, if you don't know the package, you don't know the class name,
period. The package is an intrinsic part of the name. Now, you should be
able to parse the full name from the class file, perhaps using BCEL or by
looking at the bytes yourself. A standard URLClassLoader won't load them for
you, though, since it expects a class foo.bar.Baz in a directory structure
matching the package name: <base url>/foo/bar/Baz.class. A custom class
loader should do the job, though.
HTH,
Michiel



I would like to be able to read in the classname bytes themselves...
but I haven't found the specs that tell me where these bytes are
stored however. Where should I look for this?

Thanks,
Cory
 
A

Anton Spaans

Hi Cory,

Here is your example code:
===========================
private Class fileToClass(File file) throws IOException {
int magic = 0xCAFEBABE;
String name = file.getName();
Class retClass = null;

if(!file.exists() || !name.endsWith(".class")) {
return null;
}

DataInputStream dataIn = new DataInputStream(
new FileInputStream(file));
if(dataIn.readInt() == magic) {
//Now we know it's a Java CLASS file
URL[] url = new URL[1];
url[0] = file.toURL();

URLClassLoader urlLoader = new URLClassLoader(url);

try {
retClass = urlLoader.loadClass("com.hey.now.MyClass"));
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}

// TODO Auto-generated method stub
return retClass;
}
===============
First of all, the URLClassLoader constructor takes an array of URLs, each
URL describing a *class-path* definition. This means that URLs (as strings)
such as "java/lang/String.class" is not accepted. This and your example URL
refers to a *class*, not a class-path. A valid URL-example would be
"D:/MyProjects/Project1/classes" or "D:/MyLibs/lib1.jar".

In your code, you have the variable 'file'. Call 'file.getCanonicalPath()'
to get a fully qualified path-definition of your file. Then figure out what
part of the returned string is the class-path definition. The tail
(remainder) is your class definition:

E.g. Suppose file.getCanonicalPath() returns
"D:/MyProjects/Project1/classes/com/hey/now/MyClass.class". Then you need to
figure somehow out that "D:/MyProjects/Project1/classes" is the class-path
definition you want. Then remove "D:/MyProjects/Project1/classes" form
"D:/MyProjects/Project1/classes/com/hey/now/MyClass.class". This will result
in this string: "com/hey/now/MyClass.class". Then translate all '/' (or '\')
into dots '.' and remove the ".class" post-fix: "com.hey.now.MyClass".

The tricky part here is how to figure out the class-path definition
"D:/MyProjects/Project1/classes". But as soon as you have this class-path
definition, use it in the constructor of URLClassLoader:

String classPath = ..... // "D:/MyProjects/Project1/classes"
String className = .... // "com.hey.now.MyClass"
...
urlLoader = new URLClassLoader(new URL[] { new URL(classPath) });
...
retClass = urlLoader.loadClass(className);

Hopes this helps!
-- Anton.
 
C

Cory

Michiel Konstapel said:
Basically, if you don't know the package, you don't know the class name,
period. The package is an intrinsic part of the name. Now, you should be
able to parse the full name from the class file, perhaps using BCEL or by
looking at the bytes yourself. A standard URLClassLoader won't load them for
you, though, since it expects a class foo.bar.Baz in a directory structure
matching the package name: <base url>/foo/bar/Baz.class. A custom class
loader should do the job, though.
HTH,
Michiel


Ah. I found/dled and looked over BCEL. It seems a bit overkill for the
task but def. looks to be interesting for later ptojects. Do you have
any suggestions as far as BCEL tutorials go? There's aren't m/any that
I've found.

Thanks in advance,
-Cory
 
C

Cory

Anton Spaans said:
Hi Cory,

Here is your example code:
===========================
private Class fileToClass(File file) throws IOException {
int magic = 0xCAFEBABE;
String name = file.getName();
Class retClass = null;

if(!file.exists() || !name.endsWith(".class")) {
return null;
}

DataInputStream dataIn = new DataInputStream(
new FileInputStream(file));
if(dataIn.readInt() == magic) {
//Now we know it's a Java CLASS file
URL[] url = new URL[1];
url[0] = file.toURL();

URLClassLoader urlLoader = new URLClassLoader(url);

try {
retClass = urlLoader.loadClass("com.hey.now.MyClass"));
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}

// TODO Auto-generated method stub
return retClass;
}
===============
First of all, the URLClassLoader constructor takes an array of URLs, each
URL describing a *class-path* definition. This means that URLs (as strings)
such as "java/lang/String.class" is not accepted. This and your example URL
refers to a *class*, not a class-path. A valid URL-example would be
"D:/MyProjects/Project1/classes" or "D:/MyLibs/lib1.jar".

In your code, you have the variable 'file'. Call 'file.getCanonicalPath()'
to get a fully qualified path-definition of your file. Then figure out what
part of the returned string is the class-path definition. The tail
(remainder) is your class definition:

E.g. Suppose file.getCanonicalPath() returns
"D:/MyProjects/Project1/classes/com/hey/now/MyClass.class". Then you need to
figure somehow out that "D:/MyProjects/Project1/classes" is the class-path
definition you want. Then remove "D:/MyProjects/Project1/classes" form
"D:/MyProjects/Project1/classes/com/hey/now/MyClass.class". This will result
in this string: "com/hey/now/MyClass.class". Then translate all '/' (or '\')
into dots '.' and remove the ".class" post-fix: "com.hey.now.MyClass".

The tricky part here is how to figure out the class-path definition
"D:/MyProjects/Project1/classes". But as soon as you have this class-path
definition, use it in the constructor of URLClassLoader:

String classPath = ..... // "D:/MyProjects/Project1/classes"
String className = .... // "com.hey.now.MyClass"
...
urlLoader = new URLClassLoader(new URL[] { new URL(classPath) });
...
retClass = urlLoader.loadClass(className);

Hopes this helps!
-- Anton.



Thanks for your reply Anton. I've used the code that loads the url
into the URLClassloader before and it seems to work ok. As for the
package name, I am not making the assumption that the class file is in
the correct directory. In fact, it could be in any directory. I'm
going to look into BCEL and getting the "this_class" entry in the
constant pool of the byte code in order to find the fully qualified
class name.

Thanks again,
Cory Virok
 
M

Michiel Konstapel

Ah. I found/dled and looked over BCEL. It seems a bit overkill for the
task but def. looks to be interesting for later ptojects. Do you have
any suggestions as far as BCEL tutorials go? There's aren't m/any that
I've found.

Sorry, never used it, but it seemed interesting for this case.
Michiel
 
C

Cory

Michiel Konstapel said:
Sorry, never used it, but it seemed interesting for this case.
Michiel

Exactly what I was looking for! Just thought I'd post for others to
see:

ClassParser parser = null;
JavaClass c = null;
try {
parser = new ClassParser(new FileInputStream(new
File("C:\\eclipse\\workspace\\TestingWebsite\\bin\\ConvoEvent.class")),
"ConvoEvent.class");
c = parser.parse();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

System.out.println(c.getClassName());
 
Joined
May 31, 2011
Messages
1
Reaction score
0
BCEL is great for looking up the package name for an arbitrary Java .class file.

Here's some code to get you started:

import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.JavaClass;

/**
* Print out the package a Class file belongs to. I wrote this because
* the 'javap' command does not print the package name of an arbitrary
* class file.
*
*/
public class JavaClassInfo
{
public static void main(String[] args) throws Exception
{
ClassParser parser = new ClassParser(args[0]);
JavaClass javaClass = parser.parse();
System.out.println("Package: "+javaClass.getPackageName());
}
}

Now set your CLASSPATH to include the BCEL jar file and this java class. Then execute the following statement from the command line.

java JavaClassInfo SomeClassFile.class
 
Last edited:

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,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top