docs: public static TaskManagerServices fromConfiguration(
  			TaskManagerServicesConfiguration taskManagerServicesConfiguration,
  			TaskManagerMetricGroup taskManagerMetricGroup,
  			ResourceID resourceID,
  			Executor taskIOExecutor,
  			long freeHeapMemoryWithDefrag,
  			long maxJvmHeapMemory) throws Exception {
  
  		// pre-start checks
  		checkTempDirs(taskManagerServicesConfiguration.getTmpDirPaths());
  
  		final TaskEventDispatcher taskEventDispatcher = new TaskEventDispatcher();
  
  		final NetworkEnvironment network = new NetworkEnvironment(
  			taskManagerServicesConfiguration.getNetworkConfig(), taskEventDispatcher, taskManagerMetricGroup);
  		network.start();
  
  		final KvStateService kvStateService = KvStateService.fromConfiguration(taskManagerServicesConfiguration);
  		kvStateService.start();
  
  		final TaskManagerLocation taskManagerLocation = new TaskManagerLocation(
  			resourceID,
  			taskManagerServicesConfiguration.getTaskManagerAddress(),
  			network.getConnectionManager().getDataPort());
  
  		// this call has to happen strictly after the network stack has been initialized
  		final MemoryManager memoryManager = createMemoryManager(taskManagerServicesConfiguration, freeHeapMemoryWithDefrag, maxJvmHeapMemory);
  
  		// start the I/O manager, it will create some temp directories.
  		final IOManager ioManager = new IOManagerAsync(taskManagerServicesConfiguration.getTmpDirPaths());
  
  		final BroadcastVariableManager broadcastVariableManager = new BroadcastVariableManager();
  
  		final List<ResourceProfile> resourceProfiles = new ArrayList<>(taskManagerServicesConfiguration.getNumberOfSlots());
  
  		for (int i = 0; i < taskManagerServicesConfiguration.getNumberOfSlots(); i++) {
  			resourceProfiles.add(ResourceProfile.ANY);
  		}
  
  		final TimerService<AllocationID> timerService = new TimerService<>(
  			new ScheduledThreadPoolExecutor(1),
  			taskManagerServicesConfiguration.getTimerServiceShutdownTimeout());
  
  		final TaskSlotTable taskSlotTable = new TaskSlotTable(resourceProfiles, timerService);
  
  		final JobManagerTable jobManagerTable = new JobManagerTable();
  
  		final JobLeaderService jobLeaderService = new JobLeaderService(taskManagerLocation, taskManagerServicesConfiguration.getRetryingRegistrationConfiguration());
  
  		final String[] stateRootDirectoryStrings = taskManagerServicesConfiguration.getLocalRecoveryStateRootDirectories();
  
  		final File[] stateRootDirectoryFiles = new File[stateRootDirectoryStrings.length];
  
  		for (int i = 0; i < stateRootDirectoryStrings.length; ++i) {
  			stateRootDirectoryFiles[i] = new File(stateRootDirectoryStrings[i], LOCAL_STATE_SUB_DIRECTORY_ROOT);
  		}
  
  		final TaskExecutorLocalStateStoresManager taskStateManager = new TaskExecutorLocalStateStoresManager(
  			taskManagerServicesConfiguration.isLocalRecoveryEnabled(),
  			stateRootDirectoryFiles,
  			taskIOExecutor);
  
  		return new TaskManagerServices(
  			taskManagerLocation,
  			memoryManager,
  			ioManager,
  			network,
  			kvStateService,
  			broadcastVariableManager,
  			taskSlotTable,
  			jobManagerTable,
  			jobLeaderService,
  			taskStateManager,
  			taskEventDispatcher);
  	}