@Override
    public ClassLoaderLease registerClassLoaderLease(JobID jobId) {
        synchronized (lockObject) {
            return cacheEntries
                    .computeIfAbsent(jobId, jobID -> new LibraryCacheEntry(jobId))
                    .obtainLease();
        }
    }
@Test
    public void releaseUserCodeClassLoader_willRegisterOnce()
            throws IOException, InterruptedException {
        final BlobLibraryCacheManager libraryCacheManager =
                new TestingBlobLibraryCacheManagerBuilder().build();

        final LibraryCacheManager.ClassLoaderLease classLoaderLease =
                libraryCacheManager.registerClassLoaderLease(new JobID());
        final UserCodeClassLoader userCodeClassLoader =
                classLoaderLease.getOrResolveClassLoader(
                        Collections.emptyList(), Collections.emptyList());

        final OneShotLatch releaseHookLatch = new OneShotLatch();
        userCodeClassLoader.registerReleaseHookIfAbsent("test", releaseHookLatch::trigger);
        userCodeClassLoader.registerReleaseHookIfAbsent(
                "test",
                () -> {
                    throw new RuntimeException("This hook is not expected to be executed");
                });

        classLoaderLease.release();

        // this will wait forever if the second hook gets registered
        releaseHookLatch.await();
    }