public void go(boolean shouldLoop, AgentBootstrapperArgs bootstrapperArgs) {
        loop = shouldLoop;
        launcherThread = Thread.currentThread();

        validate();
        cleanupTempFiles();

        int returnValue = 0;
        DefaultAgentLaunchDescriptorImpl descriptor = new DefaultAgentLaunchDescriptorImpl(bootstrapperArgs, this);

        do {
            ClassLoader tccl = launcherThread.getContextClassLoader();
            try (AgentLauncherCreator agentLauncherCreator = getLauncherCreator()) {
                AgentLauncher launcher = agentLauncherCreator.createLauncher();
                LOG.info("Attempting create and start launcher...");
                setContextClassLoader(launcher.getClass().getClassLoader());
                returnValue = launcher.launch(descriptor);
                resetContextClassLoader(tccl);
                LOG.info("Launcher returned with code {}(0x{})", returnValue, Integer.toHexString(returnValue).toUpperCase());
                if (returnValue == AgentLauncher.IRRECOVERABLE_ERROR) {
                    loop = false;
                }
            } catch (Exception e) {
                LOG.error("Error starting launcher", e);
            } finally {
                resetContextClassLoader(tccl);
                forceGCToPreventOOM();
            }

            // Immediately restart if launcher isn't up to date.
            if (returnValue != AgentLauncher.NOT_UP_TO_DATE) {
                waitForRelaunchTime();
            }
        } while (loop);

        LOG.info("Agent Bootstrapper stopped");

        jvmExit(returnValue);
    }
@Test
    @Timeout(10)
    public void shouldNotRelaunchAgentLauncherWhenItReturnsAnIrrecoverableCode() {
        final boolean[] destroyCalled = new boolean[1];
        final AgentBootstrapper bootstrapper = new AgentBootstrapper(){

            @Override
            AgentLauncherCreator getLauncherCreator() {
                return new AgentLauncherCreator() {
                    @Override
                    public AgentLauncher createLauncher() {
                        return descriptor -> AgentLauncher.IRRECOVERABLE_ERROR;
                    }

                    @Override
                    public void close() {
                        destroyCalled[0] = true;
                    }
                };
            }
        };

        final AgentBootstrapper spyBootstrapper = stubJVMExit(bootstrapper);

        try {
            spyBootstrapper.go(true, new AgentBootstrapperArgs().setServerUrl(new URL("http://" + "ghost-name" + ":" + 3518 + "/go")).setRootCertFile(null).setSslVerificationMode(AgentBootstrapperArgs.SslMode.NONE));
        } catch (Exception e) {
            fail("should not have propagated exception thrown while invoking the launcher");
        }
        assertThat(destroyCalled[0], is(true));
    }