Plugin statuses and behaviors
- Tested in Jenkins 1.532.1.
Status |
|
| Load class from your plugin |
---|---|---|---|
Not installed | false | NPE | Fail |
Installed without restart | true | true | Fail (JENKINS-19976) |
Installed without restart before your plugin | true | true | Succeed |
Installed | true | true | Succeed |
Uninstalled and not restarted | true | true | Succeed |
Disabled and not restarted | true | false | Succeed |
Disabled | false | NPE | Fail since Jenkins 1.524 |
How to test them
You can test them in Manage Jenkins > Script Console as followings:
getPlugin("dependee") != null
println(Jenkins.instance.getPlugin("pluginname-to-test"));
getPlugin("dependee").getWrapper().isEnabled()
println(Jenkins.instance.getPlugin("pluginname-to-test").getWrapper().isEnabled());
Load class from your plugin
println(Jenkins.instance.getPlugin("your-plugin-name").getWrapper().classLoader.loadClass("name-of-class-to-load"));
Codes cause class loading
When your plugin optionally depends on other plugins, you have to access classes in those plugins only when you have checked those plugins are installed.
In most cases, you can do that by testing plugin installations before executing codes that access those classes, as described in Dependencies among plugins#Optional dependencies.
However, there are cases your class causes loading other classes not when executing codes that access them, but when someone instantiates your class, or calls reflection methods for your class. Especially Descriptor#<init>
calls Class#getMethod("getDescriptor")
and it often causes those cases.
Example case
- dependee-plugin and depender-plugin both depend on base-plugin.
- depender-plugin optionally depends on dependee-plugin.
- class
Derived
in dependee-plugin extends classBase
in base-plugin.
contained in public method declarations
- Classes in public method declarations will be loaded.
Any of following public method declarations cause
Derived
loaded when SomeClass is instantiated, or someone callsSomeClass#getMethod
and so on. If dependee-plugin is not installed, it causesNoClassDefFoundError
even thoughdoSomething1()
anddoSomething2
are never executed.public class SomeClass { // They cause loading Derived even without execution. public Derived doSomething1() { // dosomething... } public void doSomething2(Derived arg0) { // dosomething... } }
- You'd better not to use classes in optional depended plugins in any method declarations.
- There might be cases even non-public (protected or private) method declarations cause class loading.
Upcasting
- If there are codes upcasting to the base class, the derived class will be loaded.
Following code cause
Derived
loaded when SomeClass is instantiated, or someone callsSomeClass#getMethod
and so on. If dependee-plugin is not installed, it causesNoClassDefFoundError
even thoughdoSomething()
are never executed.public class SomeClass { public void doSomething() { Derived d = getDrived(); Base b = (Base)d; // This causes loading Derived even without execution. ... } }
Following code also cause loading
Derived
.public class SomeClass { public void doSomething() { Derived d = getDrived(); doSomethingImpl(d); // This causes loading Derived even without execution. ... } private void doSomethingImpl(Base b) { // do something } }
Following code also cause loading
Derived
if you compile it with JDK 1.6. This does not cause a problem when you compile it with JDK 1.7.public class SomeClass { public void doSomething() { Collection<Derived> dList = getDerivedList(); for(Base b: dList) // this would be converted to for(Derived b: dList) in JDK1.6. { doSomethingImpl(d); // This causes loading Derived even without execution compiled with JDK1.6. ... } } private void doSomethingImpl(Base b) { // do something } }
Upcastings not causing class loading
Upcasting to
Object
does not cause class loading. Following code does not cause loadingDerived
.public class SomeClass { public void doSomething() { Derived d = getDrived(); Object b = (Object)d; // This causes loading Derived even without execution. ... } }
Generic types are considered only when compiling, and ignored when execution. Following code does not cause loading
Derived
.public class SomeClass { public void doSomething() { Collection<Derived> dList = getDerivedList(); Base b = (Base)dList.get(0); } }
Following code generates safe byte codes even with JDK 1.6.
public class SomeClass { public void doSomething() { Collection<Derived> dList = getDerivedList(); for(Iterator<Derived> it = dList.iterator(); it.hasNext(); ) { Base b = it.next(); ... } } private void doSomethingImpl(Base b) { // do something } }
Attachments:
SampleCase.pptx (application/vnd.openxmlformats-officedocument.presentationml.presentation)