Plugin reloading/enabling

Yeah this is really useful, and could be made a lot better if it’s integrated in sponge instead of a plugin.

Ultimately, this sounds like it could be useful, but my concern would be keeping track of dependencies. If you have plugins A, B and C, and plugin C depended on B, disabling B must disable C. Similarly, enabling C must enable B. If you reload B, will the object change (i.e. create a new object and replace the old instantiation), thus causing any references to B within C become invalid thanks to the way Java works? If you reload B, should you reload C as well for this very reason? Do you just reload all plugins when you enable/disable a plugin?

I’m sure you’ve thought of this, but it’s something worth noting - it’s probably not as simple as some may think! I guess the best way (in my mind) to go about this is to stage the changes first, so you mark for enabling/disabling every plugin that you want to change the status of first. Sponge could then calculate what other changes may be needed, and then the user can confirm the change, or abandon it. A bit like a package manger, I guess!

Regardless, if you do go down this route, there must be some very clear documentation as to what happens during an enable/disable/reload - otherwise behaviour might be undefined and weird.

(I would come into IRC to discuss this, but it’s easy to lose discussion in there, and I’m supposed to be on holiday/vacation anyway. I’m being anti-social enough by typing this out!)

3 Likes

This is not going to be possible, sorry. Pretty much everyone is against it except possibly for debugging and due to how complicated it would be even that has been ruled out.

8 Likes

I myself wrote some plugins for bukkit that don’t like reloading; simply because I am lazy.

Making sure that a plugin is able to be reloaded is much work.
And i’m not alone. Many other plugins cache external managers like the ProtocolManager from ProtocolLib.

I firmly believe it’s better to restart for reloading.

1 Like

Maybe I’m missing something entirely, but it was possible in bukkit with plugins like Plugman, so what makes it impossible in this case? Can have plugins state their dependencies so that if one is unloaded, it also unloads all dependencies before unloading the plugin you specify? Not all packages should be dependent upon each other in such a way that unloading one plugin could cascade over the rest.

I just don’t think something like this should be discounted because it’s difficult. The idea of having to restart your server for every change is ridiculous.

All plugins are loaded in a single classloader and plugins can share objects between themselves and the server without having a dependency. Those alone are enough to make /reload impossible to do. Add in to that all the various ways plugins can break /reload in Bukkit and you’ve got a recipe for disaster. I’d personally love to have it (for debugging only, screw PlugMan) but it’s just not going to happen.

Ok thanks for the information.

Just for clarification, PlugMan was less likely to work than /reload and it seemed like for most servers /reload wouldn’t work anyway. I could see a way to having /reload work (except for the ways plugins have always been able to screw it up) if someone was willing to put in the design and work but PlugMan has never been safe and there is no way to make it safe without making it impossible for plugins to interact with each other…

2 Likes

That’s kinda sad to hear :frowning:
When debugging and testing plugins it was sooo damn useful.

1 Like

See, I guess I didn’t know that. If I knew how bad it was (low level) to run commands from Plugman, I wouldn’t have made this post. At the surface, Plugman just appears to work. But I can see if it’s not done properly, it can cause some serious issues.

1 Like

Personally I think, plugin developers should care about their dependencies and make sure these are available. The only problems I had with plugman were plugins trying to access unloaded classes (e.g. Plugin A trying to hook into vault, but then vault gets unloaded…)

1 Like

@Amaranth said the truth

Plugman only call the disable and enable method of a plugin …
Sponge have not such methods.

shared objects (static fields) are not resettet, classes are already loaded, …
That create a undefined state …

It’s look like it working, but it was a horrible illusion …

BUT

Most server owner does not want a plugin reload, they only want a config reload,
and for that plugman worked mostly …

What a reload is useful for:

  • load the config again from disk
  • clear caches

What a reload can not be:

  • replace a server restart
  • a clean reset of the plugin
3 Likes

I wrote a custom plugin for my server that was able to enable/disable individual plugins on my server. The plugin made sure it wouldn’t disable itself, so it was always running. To reload a plugin, I would just disable it, and then re-enable it. Seemed to work. Having something like this built in would be nice.

The part that isn’t so nice is the disabling of dependent plugins. From a user standpoint, even if a plugin depended on another, disabling it shouldn’t disable other plugins. That’s just weird and unexpected.

1 Like

The problem with reloading plugins/mods/extensions/etc. in most languages, Java included, is that ultimately a plugin will leave references to itself in the main application or in other plugins.

In Java, for example, plugin A might use B and get a class Apple from B. Upon reloading B, A still has a copy of Apple from B but it is the old version of the class from before the reload. Java does not see the two classes to be the same and you will encounter problems.

It also risks classloader leaks, where these references stick around for a long time and compound after every restart, so you end up with a memory leak.

If you are developing, I recommend running the server from within your IDE. If you are only making minor changes (not removing or adding methods), you can just “reload changed classes” and inject your changes into the running server without restarting or reloading anything. No (manual) compilation needed. Immediate effect.

4 Likes

Ah, this makes sense.

Then isn’t there a responsibility for the developer to make sure that plugin B is loaded anytime plugin A tries to do something with it? Otherwise yes, memory leaks would occur, but that’s up to the developer. If the developer wants to be stupid, let them. stuck_out_tongue

2 Likes

I think the only way to do it in a way that is safe at all would be to enforce a policy where plugins specify their dependencies, requiring each dependency to be loaded before each plugin is. When a plugin is (un|re)loaded, all its dependees would be too. In theory it seems simple, but enforcing it might be a pain. That said, there is of course some basic stuff that Sponge could do to minimize boilerplate, like keeping track of the plugin registering each event (no idea if this is the case already yet, haven’t looked at the code quite yet).

1 Like

For those who want to make a small change to a method or something similar during debugging, if you don’t run the server from your IDE you can directly utilize the technology that it does.

It is called HotSwap, and you can even set it up on a remote server to do remote debugging (inspecting the value of variables, performing a memory dump, hot swapping running classes, etc).

An idea. I understand that plugins can mess up the reload process, but that shouldn’t be an excuse to be lazy, making code to unload files from a classpath can take a few minutes to write. In the case of plugins messing the reload process up, add a parameter to the Plugin annotation that defaults to “reloadable=false”.

If I user has made their plugin reloadable they put “reloadable=true” in their @Plugin statement. Only plugins that are marked as reloadable would be reloaded.

At the minimum there needs to be a way to add additional plugins after startup. Let’s say I put plugin A and B in, and start the sever up, then I later decide to put plugin C in, I have to restart the entire server to load 1 additional file, which is as easy to do as using a class loader on the jar file and then calling a method on the plugin to allow it to initialize.

If you make plugins add that flag. It means that devs have written code to make that possible. I think it is more logic to make the reload like this than.

/pluginname reload

The way FML is written I don’t think it is possible. I never looked deep in to FML, but I am sure it remaps a lot of classes. As this probably doesn’t hurt for sponge plugins. Their is a possible change Forge Mods could have been reloaded using the same method. Also mixed plugins/mods. Will definitely crash the server using that.

1 Like

I really hope there is no reload command. All it does is spam errors and cause issues and memory leaks. Just restart it.

1 Like