This is more of a why question (low priority) than a how question:
Background: I am developing a plug in for intellij that I am hoping to make as resistant as possible to interference from other plug-ins. In short, I would like to reduce the possibility of other plugins accessing its classes while it is running.
Approach: Where possible, I have made classes and their attributes package-private (removed the public keyword). This prevents code from other plugins (whose code is in a differently name package) from accessing the classes.
Test: I have created a second “tester” plugin that tries to access the code of the first plugin when both are loaded in the IDE. The test confirmed that making classes package-private in the first plug-in makes them inaccessible to the second plug-in.
The fun part: To push this further, i use identical package names for both plug-ins. Yet, even with identical package names, the tester plug-in cannot access the package-private classes of the first plug=in. This is the desired behaviour. Note, I checked the manifest in the jar files and the packages are not sealed.
Question: Does Intellij do anything special to enforce this separation between plug-ins even when they have the same package name? My assumption is that it provides its own class loader which does additional checks to limit access to nonpublic classes from other jar files.
Each plugin has its own classloader.
Out of the box, an independent plugin (i.e. your tester plugin) does not have access to the other one.
But, if you add a dependency in your tester plugin on the other plugin, then the classloader of the tester plugin will have access to the classes of the first plugin. It has to, because with a dependency the tester plugin is allowed to use classes of its dependencies.
AFAIK things may be a bit different with the newer v2 plugin descriptor model.
Because all plugins run in the same JVM process, hacks with e.g. reflection are always possible.
You won’t be able to change the fundamental design of the IDE’s plugin system, so I’d just not worry about it. You can’t change it, anyway.
Thank you for the quick reply. My tester (second) plugin does have an explicit dependency on the first. And, it can access all public classes of the first plug-in, as expected. But, an IllegalAccess Error is generated if it tries to access any of the package-private classes.
In my test, I have a Service in the first plugin that the second plugin attempts to gain access to through the Application.getApplication().getService(TargetClass.class)
If the TargetClass is public, this succeeds. If not, an IllegalAccess Error is generated.
I would assume that the JVM would prevent code from one package accessing package-private code of another package. So, the question is, is code, with the same package name but coming from two different jar files considered to be all in the same package?
Great question: I am developing a plugin that will be used to create a controlled environment for conducting programming examinations. As such, my goal is to “harden” the plug-in to make it more challenging for students to cheat. I agree that making it bullet proof is impossible.
It does appear (based on my experiments) with the standard VM installed with intellij, that package-private classes in the target plugin are not accessible to attacking plugin even when
the dependency is specified (attacker depends on target),
both the target plugin and the attacking plugin are in the same package (i.e, the package statements at the top of the code files are identical), and
the plugins have different plugin IDs.
In short it appears that the VM is preventing the attacker plugin from accessing the target plugin. Which is my desired objective.
@changjiong.liu 's explanation helped me better understand why this is so.