diff --git a/CRM/Utils/Hook/Joomla.php b/CRM/Utils/Hook/Joomla.php
index 77377e3c6d38..e844c4abbb40 100644
--- a/CRM/Utils/Hook/Joomla.php
+++ b/CRM/Utils/Hook/Joomla.php
@@ -74,7 +74,7 @@ public function invokeViaUF(
           $app = JCli::getInstance();
         }
         else {
-          $app = JApplicationCli::getInstance();
+          $app = \Joomla\CMS\Factory::getApplication();
         }
       }
 
diff --git a/CRM/Utils/System/Joomla.php b/CRM/Utils/System/Joomla.php
index 9bedbdeff2b8..e2773fe2f25e 100644
--- a/CRM/Utils/System/Joomla.php
+++ b/CRM/Utils/System/Joomla.php
@@ -520,6 +520,10 @@ public function getVersion() {
       $version = new JVersion();
       return $version->getShortVersion();
     }
+    elseif (class_exists('Version')) {
+      $version = new Version();
+      return $version->getShortVersion();
+    }
     else {
       return 'Unknown';
     }
@@ -535,7 +539,11 @@ public function getJVersion($joomlaBase) {
         $versionPhp = $joomlaBase . '/libraries/cms/version/version.php';
       }
       require $versionPhp;
-      $jversion = new JVersion();
+      $class = 'jVersion';
+      if (!class_exists('jVersion')) {
+        $class = 'Version';
+      }
+      $jversion = new $class();
       define('JVERSION', $jversion->getShortVersion());
     }
   }
@@ -578,10 +586,17 @@ public function loadBootStrap($params = [], $loadUser = TRUE, $throwError = TRUE
     }
 
     // Get the framework.
-    if (file_exists($joomlaBase . '/libraries/import.legacy.php')) {
+    if (file_exists($joomlaBase . '/libraries/import.legacy.php') && !file_exists($joomlaBase . '/libraries/bootstrap.php')) {
       require $joomlaBase . '/libraries/import.legacy.php';
     }
-    require $joomlaBase . '/libraries/cms.php';
+
+    if (!file_exists($joomlaBase . '/libraries/bootstrap.php')) {
+      require $joomlaBase . '/libraries/cms.php';
+    }
+    else {
+      require $joomlaBase . '/libraries/bootstrap.php';
+      require_once $joomlaBase . '/includes/framework.php';
+    }
     self::getJVersion($joomlaBase);
 
     if (version_compare(JVERSION, '3.8', 'lt')) {
@@ -614,11 +629,35 @@ public function loadBootStrap($params = [], $loadUser = TRUE, $throwError = TRUE
       date_default_timezone_set($timezone);
       CRM_Core_Config::singleton()->userSystem->setMySQLTimeZone();
     }
+    if (version_compare(JVERSION, '4.0', '>=')) {
+      // Boot the DI container
+      $container = \Joomla\CMS\Factory::getContainer();
+      /*
+       * Alias the session service keys to the web session service as that is the primary session backend for this application
+       *
+       * In addition to aliasing "common" service keys, we also create aliases for the PHP classes to ensure autowiring objects
+       * is supported.  This includes aliases for aliased class names, and the keys for aliased class names should be considered
+       * deprecated to be removed when the class name alias is removed as well.
+       */
+      $container->alias('session', 'session.cli')
+        ->alias('JSession', 'session.cli')
+        ->alias(\Joomla\CMS\Session\Session::class, 'session.cli')
+        ->alias(\Joomla\Session\Session::class, 'session.cli')
+        ->alias(\Joomla\Session\SessionInterface::class, 'session.cli');
+      // Instantiate the application.
+      if (PHP_SAPI == 'cli') {
+        $app = $container->get(\Joomla\CMS\Application\ConsoleApplication::class);
+      }
+      else {
+        $app = $container->get(\Joomla\CMS\Application\AdministratorApplication::class);
+      }
+      // Set the application as global app
+      \Joomla\CMS\Factory::$application = $app;
+    }
 
     // CRM-14281 Joomla wasn't available during bootstrap, so hook_civicrm_config never executes.
     $config = CRM_Core_Config::singleton();
     CRM_Utils_Hook::config($config);
-
     return TRUE;
   }