List all public classes in a jar programatically - java

I have a jar file and I can list all classes in the jar. The classes in the jar can be public, protected or package scope. I wonder if it is possible to tell the scope and only list the public classes?

You can do so, and I can think of more than just one way how to do it, here are two:
You can use a bytecode manipulation tool to read the .class files and get the modifier. The downside is that you need an extra library for that. The upside is that this way would be quite safe, as you don't need to load the class into the VM, just into memory, so no code is executed, and if the .jar classes depend on classes which are unavailable, this way would still work.
You can use a ClassLoader with this .jar and load each of the classes, then inspect it using Reflection. The upside is that you do not need any third party libraries for this. The downside is that in order to inspect the classes, they need to be loaded by the ClassLoader, which means the code of these classes (static initializers) will be executed. If this is untrusted third party code, you will want to install a SecurityManager first to sandbox these classes. The other downside is that if these classes depend on other classes that are not available (for example by extending such unavailable classes), this approach would fail.
You can use the javap tool to inspect the classes.

If you are already listing the classes in the jar, you can use the Reflection interface to get the Class objects for those classes by name (String), and then use the Class interface to determine the properties of the class, for example isPublic, isFinal, or isStatic.
A quick search reveals:
http://tutorials.jenkov.com/java-reflection/classes.html#modifiers

Related

Java: Packaging classes with cross-module-usage

In my project (a parser for various formats), I packaged the modules by functionality but there are a few classes which are needed by every module.
Now I'm not sure what's the best practice here:
Should every module/package have a duplicate of the class? The compiler will probably optimize this anyway, won't it?
Create a "Shared" package? This doesn't feel right...
Other options?
I wouldn't package duplicates of the class, that could cause you some endless headaches, because the same class file contents loaded by different classloaders is not considered to be the same class at all by Java, so you'll get impossible to understand error messages. And if all your jars are in the same class loader, only the first class will be loaded, so you may as well put it in one place only.
I would certainly package utility classes in their own jar and have a dependency from all the other packages, as is the case with other libraries you may use etc. You can even use the classpath attribute of the manifest to reference the library easily.
I would suggest you create an abstract class and provide implentation separately in each class and package them separately.

What's the point of using .class objects?

In the past few weeks, I've run into several different peoples' code using .class objects. For example, ArrayList of classes : ArrayList<Class> but how to force those classes to extend some super class?.
I looked them up: http://docs.oracle.com/javase/tutorial/reflect/class/index.html
I'm just wondering why you'd want to use .class objects. I can see getDeclaredFields() and getDeclaredMethods() being potentially useful, but I can't really think of concrete examples as to why I'd actually want to use the .class objects in lieu of something else. Could anyone shed some light on this topic?
Thanks in advance.
I think you misunderstood the concept. Class class has nothing to do with compiled classes (.class).
Class is a class that represents a Java class internal structure, such as fields, methods, etc... This is a compile-time entity, which you can use in your code (even before compiling).
.class is a compiled Java class file, which is Java bytecode. This is not a "code" entity (you cannot use it as a class or object in your code -besides as any file-) and it is not available before compilation.
Reflection (Class is part of the reflection package) is useful when you want to do advanced stuff with the code, like manipulating it, accessing its members, getting information from it, etc...
A typical example where you want to use reflection is making a Java debugger. Since any code can be run on the debugger, you need reflection to get information about the object instances and their structure and show this to the user.
Reflection is one reason to use it. Another good example is dynamically constructing objects at runtime.
For example, the Spring framework uses configuration files that contain the names of Java classes. Somewhere in that code, Spring needs to build object instances of those classes. In this way, the objects are created without the compiler needing to know anything about the Java classes at compile time.
This can be useful when developing an interpreter of a scripting language running on JVM, which has an ability to call Java methods.
Also, might be useful in a system allowing for plugin extensions.
Another use case:
InputStream is = MyClass.class.getResourceAsStream("/some/resource/in/the/jar");
Plug-in are a big use for this.
Dynamically load .class files which are in say, your plugins folder and execute some specified function from said files. Then, you can have 0 or more plug-ins and any combination of them installed for your application at a time.

Creating an invisible class in a jar

How do I create a jar in java that only one class is visible (public) to users of the jar?
I know I can omit the "public" from the declaration of a class, which makes it visible only to that package, but how do I do it in a jar with several packages, when the visibility should be public to all the classes inside the jar, but not outside of the jar?
You're basically looking for the Java counterpart of .Net's assembly-wide visibility. I'm afraid you don't have this ability within the framework of current Java. Future version of Java will offer better support for modules, which should allow something along these lines.
You'd have to include all your classes in a single Java package, and omit the "public" modifier in the class definition.
I recommend against this. If you want to indicate a class shouldn't be used by clients of a library, put it in a package named "impl" or "internal" and don't provide public documentation.
Does using protected as modifier fix this? I know it does allow access for inherited classes, but I don't know about all the other classes in the package.
Just a wild idea, but you could play around with a custom classloader that loads files from your .jar which are not recognised as classes otherwise.
For instance you could postprocess class files by encrypting them and storing with your own file extension, then loading and decrypting them from the jar by your custom classloader from the "main" class that is visible to the users of the class. (caveat; I have never tried to do something like this myself :-))
Another method (if the code base isn't too large) might be to develop your classes like normal, run your tests on the package structure and as the last step before packaging use a (perl) script to rebuild your main class by inserting all other classes as private static inner classes and rebuild that. Using this transformation as a pre-package step means you can develop in a sane structure while hiding the implementation classes in the jar.

Is it possible to get a collection of public interfaces and classes in a package using reflection?

Is it possible to get a collection of public interfaces and classes in a given package using reflection?
Question is for Java 1.6
Why:
I have a package where some classes are annotated. I want to collect them automcatically for documenting
No, not possible, at least in general. That's because the classloader mechanism is too flexible to permit it: classes can be loaded via network or generated on the fly, and the only operation is "ask the classloader for a class with fully qualified name X, and it will either return class X or throw an exception. You could easily implement a classloader that returns an class for any name in any package, i.e. an infinite number of classes.
For the specific case of loading classes from a directory or JAR file via an URLClassLoader, it's possible to look at the contents of said directory or JAR file.
Do you really have to generate the documentation at runtime? The normal way to use the annotation processing tool (APT): http://download.oracle.com/docs/cd/E17476_01/javase/1.5.0/docs/guide/apt/GettingStarted.html

Creating a java library

This may be a silly question, but right now I have a rather large class that I want to use as a library. Where somebody can simply add this jar file to their classpath. And then simply do an import statement at the top, then he or she can start using this class.
Is there anything special I need to do or can I simply just use the jar file built?
a rather large class
Large classes don't usually make good libraries :)
Technically, yeah, all you need it put it in a JAR. To make it easy to use (including by yourself), you should spend some time to refactor it and break up the functionality into smaller classes according to the Single Responsibility Principle. For static utility methods, consider whether you can group them into several classes according to some theme, or perhaps even turn some of them into non-static methods (if there are situations where a client would use more than one of those methods on the same data, they're begging to become instance methods).
And you definitely should write Javadoc comments for all public classes and methods, and publish the Javadocs along with the code. A library without an API doc is almost useless.
You can simply put the JAR into the classpath and can import the class. No more magic needed.
You should just be able to use the jar, as is. All you need to ensure is that the class files in the JAR are in the correct directory structure (according to their package names)
Class Foo in package bar -> bar/Foo.class in the jar
create a JAR of .class files of your "large class" and then put that JAR in your CLASSPATH.
Then you should be able to import the classes in the JAR via "import" statements.
If you anticipate too many huge classes/libraries, check out the JVM parameters -Xms and -Xmx that takes care of heap usage.

Categories