class DataItemCache {
private CompletableFuture future;
public DataItemCache() {
future = CompletableFuture.completedFuture(null);
}
public void saveItemAsync(Object dataItem) {
future = future.thenRunAsync(() -> {
saveItemSync(dataItem); // Saves the item to Elastic Search
});
}
public void waitForWriteComplete() {
future.get();
}
Этот класс используется следующим образом:
class DataProcessorIntegrationTest {
@Inject private DataItemCache dataItemCache;
@Before
public void setup() {
// Setup Guice for injection
}
@Test
public void testWorkflow() {
int numItems = 1000;
for (int index = 0; index < numItems; index++) {
DataItem obj = ... // build data item
dataItemCache.saveItemAsync(obj);
}
// I have code to periodically dump the heap during this wait
dataItemCache.waitForWriteComplete();
// assert that Elastic Search has 1000 items
}
}
Количество элементов данных, выделенных непосредственно перед возвратом функции waitForWriteComplete(), равно 1000, а сразу после этого равно 0. Я ожидаю, что количество элементов данных будет меньше 1000, так как некоторые из них завершили запись в Elastic Search ( Я знаю это из журналов консоли).
Когда я запускаю этот код в производство, я получаю OOM. Проверка кучи во время OOM показывает миллионы объектов DataItem и CompletableFuture. Очевидно, что многие из них должны были завершить написание и вернуться из метода saveItem. Почему такие объекты DataItem и CompletableFuture не освобождаются?
Любые идеи о том, как решить эту проблему?
dataItem
иCompletableFutures
не освобождаются, то покажите части кода, где вы ожидаете, что они станут подходящими для GC. - person Kayaman   schedule 18.01.2018future
, который у вас есть вDataItemCache
, бесполезен, он вам не нужен для запуска асинхронного кода, а вашwaitForWriteComplete()
ничего не будет ждать, так какfuture
уже завершен с самого начала.get()
не ждет зависимых задач. На самом деле, я даже не думаю, чтоthenRunAsync()
отслеживает какие-либо зависимые этапы после того, как будущее, на котором оно вызывается, было завершено (это может быть источником утечек памяти). В любом случае, до сих пор нет правильного кода, чтобы понять и воспроизвести проблему. Это все еще не минимально воспроизводимый пример. - person Didier L   schedule 18.01.2018DataItemCache
объявляется и используется в производстве так как здесь нет ни аннотаций, ни примера кода — просто юнит-тест, который, как я понимаю, не воспроизводит проблему. - person Didier L   schedule 18.01.2018