Obtaining Java source code from class name - java

Is there a way to obtain the Java source code from a class name?
For example, if I have access to the library with the class java.io.File, I want its source code.
I am working on a kind of parser and I need the source at execution time. I have also to search it recursively.
Say the aforementioned class has this method:
int method (User user) {...}
I would need to obtain User's source code, and so on and so forth with its inner classes.

Is there any way to obtain the java source from a class name? For example:...
You may want one of several possible solutions. Without knowing what you really want to do with the information, we can't be very precise with our recommendations, but I'd start by steering you away from source code if possible. JSE source code is available online, as are many open source libraries, but that may not always be the case. Additionally, you'll need to keep it all organized when you want to find it, much like a classpath, whereas the Class objects are much easier to get hold of, and manipulate, without having to parse text again.
Reflection
If you just need information about a class at runtime, just use the Java Reflection API. With it, given a Class object you can, for example, get the types of a specific field, list all fields and iterate over them, etc...:
Class clazz = User.class;
Field field = clazz.getDeclaredField("var");
System.out.println(field.getType().getName());
Reflection is useful for discovering information about the classes in the program, and of course you can walk the entire tree without having to find source code, or parse anything.
Remember you can lookup a class object (as long as it's on the classpath at runtime) with Class.forName("MyClass") and reflect on the resulting Class.
Bytecode Manipulation
If you need more than information, and actually want to manipulate the classes, you want bytecode manipulation. Some have tried to generate source code, compile to bytecode and load into their program, but trust me - using a solid bytecode manipulation API is far, far easier. I recommend ASM.
With it, you can not only get information about a class, but add new fields, new methods, create new classes... even load multiple variations of a class if you're feeling self-abusive. An example of using ASM can be found here.
Decompilation
If you really, really do need the source, and don't have it available, you can decompile it from a class object using one of the various decompilers out there. They use the same information and techniques as the above two, but go further and [attempt] to generate source code. Note that it doesn't always work. I recommend Jode, but a decent list, and comparison of others is available online.
File Lookup
If you have the source and really just want to look it up, maybe all you need is to put the .java files somewhere in a big tree, and retrieve based on package name as needed.
Class clazz = User.class;
String path = clazz.getPackage().getName().replaceAll("\\.","/");
File sourceFile = new File(path, clazz.getName() + ".java")
You want more logic there to check the class type, since obviously primatives don't have class definitions, and you want to handle array types differently.
You can lookup a class by name (if the .class files are on your classpath) with Class.forName("MyClass").

You can get a good approximation of the source from a class file using the JAVA decompiler of your choice. However, if you're really after the source of java.io.File then you can download that.

The best and simplest bet can be javap
hello.java
public class hello
{
public static void main(String[] args)
{
System.out.println("hello world!");
world();
}
static public void world()
{
System.out.println("I am second method");
}
}
do a javap hello and you will get this:
Compiled from "hello.java"
public class hello extends java.lang.Object{
public hello();
public static void main(java.lang.String[]);
public static void world();
}

Yes, if you download the source code. It's available for public download on the official download page.
If you're using Eclipse whenever you use the class you could right click > View Source (or simply click the class > F3) and it'll open a new tab with the source.

You can print the resource path from where the class was loaded with
URL sourceURL=obj.getClass().getProtectionDomain().getCodeSource().getLocation();
It will be a .class file , .jar,.zip, or something else.

So what you're trying to do is get the Java class at execution. For this, you need Java reflections.

If your goal is to get information about what's in a class, you may find the Java reflection API to be an easier approach. You can use reflection to look up the fields, methods, constructors, inheritance hierarchy, etc. of a class at runtime, without needing to have the source code for the class available.

Is there any way to obtain the java source from a class name?
The answer is complicated, not least because of the vagueness of your question. (Example notwithstanding).
In general it is not possible to get the real, actual Java source code for a class.
If you have (for example) a ZIP or JAR file containing the source code for the classes, then it is simple to extract the relevant source file based on the classes fully qualified name. But you have to have gotten those ZIP / JAR files from somewhere in the first place.
If you are only interested in method signatures, attribute names and types and so on, then much of this information is available at runtime using the Java reflection APIs. However, it depends on whether the classes were compiled with debug information (see the -g option to the javac compiler) how much will be available. And this is nowhere like the information that you can get from the real source code.
A decompiler may be able to generate compilable source code for a class from the bytecode files. But the decompiled code will look nothing like the original source code.
I guess, if you have a URL for a website populated with the javadocs for the classes, you could go from a class name, method name, or public attribute name to the corresponding javadoc URL at runtime. You could possibly even "screen scrape" the descriptions out of the javadocs. But once again, this is not the real source code.

Related

Copy class but overwrite the existing class imports

I have a class with an existing import:
import org.packageA.Peeler
public class Potato {
Peeler peeler = new Peeler();
}
I'd like to be able to copy this class or create an object with it but change "import org.packageA.Peeler" to "import org.packZ.Peeler".
Is this possible to do dynamically?
No.
import statements are a bit of a misnomer. import com.foo.A; means: Anytime I write just A in this source file, imagine I wrote com.foo.A and that is all it means. It does not mean: Initialize this class or parse this source file or any other such thing (which is usually what import means in other environments).
Thus, what you're asking is: Can I take class Potato { org.packA.Peeler peeler = new org.packA.Peeler(); } and somehow dynamically create a different Potato class that is as if I wrote class Potato { org.packA.Peeler peeler = new org.packA.Peeler(); } - to which the answer is no; org.packA.Peeler is as related to org.packZ.Peeler as guns and grandmas (i.e.: That they have the same name is immaterial).
Even if you could, what would that mean? Java is statically and nominally typed, it wouldn't be possible to write code that refers to this rewritten potato class without using reflection or dynamic code generation which, in java at any rate, are almost always the wrong answer.
Some exotic options you do have:
Use a regexp or build script plugin to make a source file with some renames applied and include it in the build and compilation process (bad idea, but I guess you can do that)
Use ASM, BCEL or some other classfile tool to create a new class file in byte array form with renames applied, have a custom classloader that dynamically loads this, and then generate bytecode that uses this, or use reflective access. This is extremely convoluted, requires a ton of code, and is almost useless.
Perhaps take a step back and explain the problem you have that made you think: I know! I'll dynamically rewrite this class to use a different package! But I don't know how so I'll ask SO - except you're asking the wrong question, ask about your original problem.

Obtaining a list of all used class names from a Java source code

I am looking for a Java library (source code parser) that would help me extract unqualified names of all class names being used in the source code. For example for the given code example:
public class Example {
private ClassName1;
protected ClassName2 instance = new ClassName2();
public Example() {
ClassName3 test = new ClassName3();
}
public doSomething() {
//ClassName4 test = new ClassName4("SomeExampleString");
ClassName5 test = new ClassName5("ExampleString2");
}
}
I need to get the following list:
ClassName1, ClassName2, ClassName3, ClassName5
as this is the list of all names of classes that are being "used" in the source code.
So far I have tried to write a simple parser that would do this for me but is not robust enough to be used in the real world. I have looked into a few Java parsers too, but the problem is that I don't know how this problem would be called to look into their code for a solution, which I believe exists in the domain of existing Java parsers.
So what I am looking for is a Java source parser that would allow me to obtain a class name lists like the one in the example and a short example on how to achieve this or directions where to look for / how this problem is properly called.
NOTE: I am not looking for a method to detect all classes loaded by JVM nor classes in classpath, but a way to detect classes in textual sense by parsing original Java source code that is not compiled.
If you're just looking for a robust parser, looks like javaparser is pretty good.
You may want to check out this question where the solution is to view all of the classes loaded by the JVM by using the -verbose:class flag. One answer there also mentions using reflection (which was my initial reaction) with this API.
If that question doesn't completely solve your problem (since it would show all classes loaded, "used" or not), and you're not having any luck with reflection, you could try something like this that combines the first solution from there with my idea:
Use whatever parser you have to parse tokens in the source code
Use the -verbose:class flag when running some main program that instantiates the class in the file you want to check
grep whatever tokens your parser tokenized from that output
So, some program Main.java:
public class Main {
public static void main(String[] args) {
Example e = new Example();
}
}
Your (or some other) parser with a main method (psuedo-code):
tokens = parse_tokens()
print "\\\|".join(tokens)
And in bash:
javac *.java
TOKS="$(java MyParser Example.java)"
java -verbose:class Main | grep ${TOKS}
That way, you don't need a robust parser, just something to tokenize Java code. Just a thought, not sure if that would work perfectly or not.

Extracting class usage from within Java methods using ctags

I would like to know if it is possible to use ctags to extract class usage from within Java methods. So far, I was able to only use it to get a listing of methods and instance variables but not which classes are utilized within methods.
E.g.
...
public void doSomething(MyClass myClassInst) {
int someVar = myClassInst.getSomeVar();
System.out.println("Some var is " + someVar);
}
...
Right now all I get is a recognition of the method declaration. But I would like to extract that doSomething is also utilizing the classes MyClass and System but not just to parse the text but also know the full class address including the package (java.lang.System and com.mypackage.MyClass).
In order to be able to extract this kind of metadata, ctags would need to have access to the compiler's abstract syntax tree and I am not sure if it does that or it simply does text parsing of the source code.
Is there a way to accomplish what I am trying to do using ctags or does it eclipse the scope of its functionality?
You can use asm or BCEL to achieve this.

How to link an Object file of class with a source file

I want to know if i can link and compile source code file with an object file of a class without including class source files.
Or
Like in Java i can give a compiled *.class file to a friend and the doc of that class without giving the source code and he can include that class for his need without knowing the real source.
Can i do the exact thing with C++ ? and How ?
FYI:I'm using MinGW.
I'm quite new to so this may look like a dumb question (but still there's no dumb questions).
In C++ you can just produce an executable file (.exe in windows, usually no extension in Linux) or a library file (.lib or .a) or a shared libarary (.dll or .so) depending on what you want to achieve.
If you are providing a library, you will have to provide a header file with the class declarations as well. If you don't want to give out too much about the details, you can have a "implementation" class that is simply a pointer to the implementation in your header file, and the real implementation is only available to you as the owner of the sources.
For more information, you should look up "PIMPL" as Thomas Matthews suggested - that's short for "Pointer to IMPLementation class". Basically, your "public" class is just a shell providing the functions you want others to see, and the implementation class inside it does all the hard work.
Simple example
In your header file:
// Forward declaration of the implementation class.
class double_it_impl;
// Class that stores an integer, and doubles it each time you
// call doubling().
class Public_double_it
{
public:
public_double_it(int x); // COnstructor.
int doubling(); // Function d
private:
double_it_impl *pImpl;
};
In your source or private header file, we declare the actual implementation:
class double_it_impl
{
public:
double_it_impl(int x) : m_x = x; {};
int doubling() { m_x *= 2; return m_x; }
}
public_double_it::public_double_it(int x)
{
pImpl = new public_double_it(x);
}
int public_double_it::doubling()
{
return pImpl->doubling();
}
Now you can't see what the implementation class contains or how it works - of course, this is a very trivial example, but I hope it conveys the idea.
You can give them the *.class but they can be decompiled.
Most libraries are provide using the classes and the generated Javadoc.
You could compile the class into a library or dll or shared library and give to your friend.
They would need a header file that defines the interface.
See also PIMPL idiom.
Yes, you can provide a compiled object file and documentation and others can link the .o (or .obj) file into their code. The exact details of how to do this vary between compilers and development environments. If you are using g++, you simply use the following command-line:
g++ -c source.cpp
This will create a .o file which you (or anyone else) can then link with other .o files with
g++ main.o source.o
Other compilers will have similar options. Read the help files and other documentation for instructions about how to create object files.
For a large number of functions and/or classes, you should look at creating a library file. These can be statically or dynamically linked. I suggest that you search the Web for more information if you want to learn about how to create your own library files.

How to access and read JVMs class file members?

I'm not very familiar with JVM and I have an assignment involving the Class file.
Write a java program that when run as
java DissectClassFile file1.class file2.class ...
it will print a summary of each class file as follows:
the name of the class defined by the class file,
its super class and interfaces it implements,
the number of items in the constant pool,
the number of interfaces implemented by the class, and their names,
the number of fields of the class whose name contain the underscore character,
the number of methods of the class whose names contain at least one capital letter
Right off the bat I don't know where to begin. If someone could help me out and point me in the correct direction, I should get the hang of it.
You need to read the Java Virtual Machine Specification. It contains an explanation of the class file format.
There is a class java.lang.Class to access that information. For every Class, you can call MyClass.class (for example, String.class) to get the object with the information for that class.
Most of this information can easily be gleaned loading each class using Class.forName(...) and using the reflection APIs to fish out the information. However the constant pool size is the killer. AFAIK, this can only be determined from the class file itself.
So, your options would seem to be:
Write a bunch of code to read and decode class files. The JVM spec has the details of the class file format.
Use an existing library such as BCEL to take care of the low-level class file parsing.
Use a hybrid of class file parsing (using either of the above) to extract the constant pool size, and the reflection APIs for the rest.
I imagine that your assignment hints at which way they expect you to go. But if not, I'd look at the BCEL approach first.

Categories

Resources