Extensions / kernel lifecycle

Let's expand kernel and extensions API to provide start / stop events, and make sure they are aligned with each other.

  1. Add Extension.uninstall(BaseKernel) - allows the kernel to shutdown extensions. This is especially useful in unit tests when multiple kernels can be created and stopped. It will allow the extensions to reset their statics.
  2. Add BaseKernel.onStartup(..) (in addition to the existing onShutdown(..)). This would allow to separate loading extensions from kernel constructor
  3. Load and "install" extensions in onStartup(..)
  4. Uninstall extensions in onShutdown(..)