2

I'm trying to get familiar with the module system introduced in Java 9, and I would like to know the best way to leverage it.

For a library I'm writing, I would like to do the following (ignore the naming of the packages):

  • Expose only interfaces, simple POJO classes, and factory classes via com.myproject.api. Everything in this class can be used by the users.
  • Put the implementation of interfaces in com.myproject.core. Users should not be able to access anything in here.

My reasoning is that users do not need to get confused or overwhelmed by the implementation logic. Instead, they can just look at (hopefully) clean and well documentated interfaces.

However, due to the way Java packages work, it can be difficult to restrict use of certain classes without making them all package private. But I don't like putting all the classes in one package, and would rather organize them into various packages.

After reading about the module system, I believe I can do the following to achieve what I want. This is the module-info.java file:

module com.myproject {
    exports com.myproject.api;
}  

From my understanding, the users of my library will be able to use everything defined in the com.myproject.api package (by using require com.mypojrect.api in their own module-info file).

But is there any way that users will be able to access anything in the com.myproject.core package? I have no problem with them looking at the code (via IDE or the source code itself), but I just don't want to end up supporting classes/methods/logic which I didn't want to expose.

I'm concerned that users who don't have a modularized application or users who put my library JAR on the classpath will somehow find a way to get access to the supposed restricted package.

Please let me know if you need any other information.

gjvatsalya
  • 1,129
  • 13
  • 29

1 Answers1

6

A pre-JDK9 user of your library cannot exist, as you're going to use the Java Platform Module System, which is post-JDK8, and thus you're going to compile to a class version greater than 52.

Said that, your users will be able to look at the source code (if shipped), and obviously they will be able to extract your .class files.


By definition

a type in a module is not accessible to other modules unless it’s a public type and you export its package.

The only way to gain Reflective access to your classes would be if you willingly opened them, with the

opens your.package

directive. So basically, you're covered also on the Reflection aspect.
And the opens directive exposes to Reflection only public definitions.


If you want to control Reflective access to your classes in a non-modular/pre-JDK9 environment, SecurityManager might be what you're looking for. However this requires access to the JVM configuration.

LppEdd
  • 20,274
  • 11
  • 84
  • 139
  • @GhostCat well I specified also `.class` files. They can be de-obfuscated. But that's a bit out-of-scope. – LppEdd Mar 14 '19 at 14:23
  • 1
    @GhostCat added clarification. – LppEdd Mar 14 '19 at 14:24
  • Yeah, well. Actually alone *de-compiling* byte code back to source code is a pretty sad thing in Java, and the whole point of an obfuscator is to NOT make it easy to get back to readable source code. But still, good answer, you got my vote here ;-) – GhostCat Mar 14 '19 at 14:25
  • @GhostCat Yeah, but look at JetBrains products. The paid editions aren't even obfuscated. They're just protected by a licence which prohibit decompilation. I think obfuscating class' files isn't even a thing anymore. The important parts are compiled to native code. And thanks for the vote :) – LppEdd Mar 14 '19 at 14:27
  • I was unaware that a pre-JDK9 user would not able to able to use a modular library. This holds true even if they build my library using JDK9+, and put the resulting JAR in in their pre-JDK9 application? If so, that's good to know. – gjvatsalya Mar 14 '19 at 14:35
  • Also - what about users who are JDK9+ but didn't modularize their application? As in, they don't have a `module-info.java` file. – gjvatsalya Mar 14 '19 at 14:37
  • @gjvatsalya it's not only that they cannot use the JPMS, it's more that they can't run your `.class` files, as they're compiled with a newer version. Infact this "*build my library using JDK9+, and put the resulting JAR in in their pre-JDK9 application*" cannot happen at all. In case of a non-modular application, I suspect you'll have this problem, as you're back to the "old" classpath rules. – LppEdd Mar 14 '19 at 14:40
  • 1
    Obviously we are leaving java9 module ground here, but obfuscation on Android still seems to be a thing: https://stackoverflow.com/questions/17290023/obfuscation-in-android-studio – GhostCat Mar 14 '19 at 15:00
  • @GhostCat I'm not an Android developer but I think that might be because applications are architecturally "simpler". This means that using obfuscation is also simpler. Being simpler also means more easily patchable. For example I've seen a couple bigger apps which ships with native libraries developed with NDK to make it harder to break. – LppEdd Mar 14 '19 at 15:22