简体   繁体   中英

How to get as a stream any class loaded from a jar not in the classpath?

I have a web-app which I want to work roughly as follows:

Someone uploads a jar (say myjar.jar ) along with the name of class to analyze (say test.Test ). The exact purpose of analysis is irrelevant so assume that the web-app does some static analysis on it.

I am able to upload the jar and load the class in Java using the hacks described here and here (MultiClassLoader).

If I know the methods inside the class, I can invoke them using reflection. Following assumes a method with signature foo(String)

Class c = jarLoader.loadClass("test.Test", true);
Object instance = c.newInstance();
Method foo = instance.getClass().getDeclaredMethod("foo", new Class[]{String.class}); 
   // foo takes one para String             
foo.setAccessible(true);
foo.invoke(instance, (Object) "hello");             

Now, suppose, I need to find out what methods are there inside test.Test . To do this, I use the ASM framework , which needs the class as a stream . This is where I am running into a problem. I am unable to do getResourceAsStream or its equivalents. This is what I tried:

Type t = org.objectweb.asm.Type.getType(c); // uses asm library
String url = t.getInternalName() + ".class";
c.getClassLoader().getResourceAsStream(url); // gives null

Same problem if I use:

c.getClassLoader().getResourceAsStream(c.getSimpleName() + ".class");

etc.

What is the right way to get resource as stream, where the resource is a class file loaded from a jar NOT in the class path. Note that the entire thing is done via a web-app.

EDIT: Getting methods is just an example. What I really want is to get the class as a stream. I need to use ASM because it gives me other information (such as parameter names), which I cannot get via getDeclaredMethods or getMethods .

Re: "Now I need to find out what methods are there inside test.Test"

You get the class via Class c = jarLoader.loadClass("test.Test", true); . Class also has getDeclaredMethods() and getMethods() .


EDIT: @Jus12, from your second link Java Tip 70: Create objects from jar files! :

protected byte[] loadClassBytes (String className)

ASM has a ClassReader(byte[] b) constructor.

I don't know if Java offers a way to do this programmatically, but I can suggest a hack: spawn a new process with:

jar xf myjar.jar test/Test.class | javap -cp test -c Test

This should output the bytecode. Then simply redirect the output to a stream you can read from.

You can use a URLClassLoader , which takes a List of URL s in its constructor. You can then load the class by invoking the loadClass method on the URLClassLoader instance to get the Class<?> object for the class that you are after. Once you have that, you can then use reflection to create instances, and/or get general information about the class.

I have not tried, but the URLClassLoader does also have a getResourceAsStream method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM