Creating an invisible class in a jar - java

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.

Related

How to make a private package?

I'm doing a library. I have three packages:
Spreadsheet is the main package. The io package is an internal package for internal use. Unfortunately, the user can access to them since they are public classes.
I would like to keep this package, since it allows me to separate concepts while programming, but i would like to "hide" these classes to the end user.
What could i do?
It's good that you're asking yourself this question! I don't see much attention on this lately.
As OdsReader and OdsWriter are used only inside the Spreadsheet class, just move them inside the spreadsheet package, removing the public visibility keywork. They'll now be accessible only from the spreadsheed package's classes.
The solution proposed above, which is over-complicated for your use-case, and which is to use Java 9+ modules (or OSGi - please no!), is not really necessary here, but it's neverthless a step forward in maintaining definitions private and sealed, even to Reflection abusers.
As a side note, I see you've got an exceptions package.
I never recommend doing so, as you'll have to expose those exceptions' constructor to the users of your code, and they'll be able to instantiate them for no good reasons.
Move the exceptions inside the packages which uses them, and declare the constructor as package private.
Starting with java9, you can turn this library into a module. See this jigsaw tutorial.
Modules need to export a package in order for its public members to be accessible from other modules: Simply don't export your internal package, and it won't be visible.
You can also go with something like OSGi, a module system that predates java9. It too has this notion that there's a level beyond public (let's call it 'visible').
A final option is to use classloader shenanigans (where you for example rename your class files to some other extension during the build phase, and have a small bootstrapper in your visible package which creates a classloader that loads classes by looking in the same place as the visible API, and then load files with the alternative extension, and defineClass those into being), but that's a drastic step that introduces quite a bit of headache. I wouldn't take it unless you have excellent reasons to go down this rabbit hole.

List all public classes in a jar programatically

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

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.

Java: Is it possible to close a package (restrict adding classes to it)

The title pretty much says all.
If I provide a library and someone uses it he can write classes and add them to packages that are defined by my library. However this rises security issues as this would mean that he gets access to methods within the library that are defined without access modifier.
Is there a solution to forbid a user to add classes to an existing package?
Yes (but). The sealed manifest attribute will seal a package, preventing classes from other sources from being included. (technote)
Though it kind of depends on the context. If the someone using it gets to play with the library jar file first, then it's game over.
If both the library and client code is loaded by the same class loader, then that is in generally problematic, although classes signed with different signatures cannot coexist within the same package. If different class loaders are used even with a parent-child relationship, then at runtime packages with the same name but loaded by different class loaders are different packages.
For Java PlugIn and Java WebStart, Trusted-Library manifest entry causes the jar to be slid into a parent class loader, protecting it from potentially untrusted application code.

When to package-private (no explicit modifier) in java?

I have been reading the tutorial Controlling Access to Members of a Class. I am confused what might be good use case for using package-private. Because as I understand, you can always change your package declaration to whatever the package declaration of such a class and act as if that is a public class. I understand that this is not a good thing to do, but what is stopping me?
Because as I understand, you can always change your package declaration to whatever the package declaration of such a class and act as if that is a public class
Well, for one thing, the access modifiers are there to help the developer. There's always ways around them, such as via reflection for instance.
I understand that this is not a good thing to do, but what is stopping me?
Not much really!
As a developer you can however distribute your classes in sealed .jar-files which basically means that you're not letting anyone else in to your packages.
From Sealing Packages within a JAR File
Sealing Packages within a JAR File
Packages within JAR files can be optionally sealed, which means that all classes defined in that package must be archived in the same JAR file. You might want to seal a package, for example, to ensure version consistency among the classes in your software.
A couple of reasons to use package-private classes/methods:
Implementation classes that are part of a library, but not part of the library's API. This allows you to still have modular code, and acts as a sign to users of the API that the implementation classes are not for use as part of the API.
Making things available to tests. Sometimes (particularly when working with legacy code) you need to make classes or members more visible so that you can more easily unit test them. An example might be testing a class with a method that performs a resource-intensive operation that you want to override with a no-op version in your test. Another example is a class that only gets used in one place: it doesn't want to be visible to the whole app, but it needs to be unit tested.
In both cases using package-priviate visibility helps to make your code easier to use (people using it have a better idea of the scope of the class/member's intended use), while allowing you to still have modular code.
Regarding "what is stopping me":
The Java Security mechanism is stopping you, potentially. If the "target" package is sealed and signed, then Java will not allow any source other than the original to declare classes in that package.

Categories