From 00688d70f5c5147e839991c9997d9182c3c443c2 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Tue, 1 Jun 2021 15:11:23 +0200 Subject: [PATCH] Make FlightRecorderApplicationStartup thread safe Prior to this commit, in some cases application context startup steps could be created concurrently, which could cause issues with the current implementation tracking the parent/child relationship between steps. This commit ensures that the flight recorder implementation is using thread safe collection implementations for that. Fixes gh-26941 --- .../jfr/FlightRecorderApplicationStartup.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/metrics/jfr/FlightRecorderApplicationStartup.java b/spring-core/src/main/java/org/springframework/core/metrics/jfr/FlightRecorderApplicationStartup.java index 3959017dbde7..b59f931483d3 100644 --- a/spring-core/src/main/java/org/springframework/core/metrics/jfr/FlightRecorderApplicationStartup.java +++ b/spring-core/src/main/java/org/springframework/core/metrics/jfr/FlightRecorderApplicationStartup.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,9 @@ package org.springframework.core.metrics.jfr; -import java.util.ArrayDeque; import java.util.Deque; +import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.concurrent.atomic.AtomicLong; import org.springframework.core.metrics.ApplicationStartup; import org.springframework.core.metrics.StartupStep; @@ -37,24 +38,23 @@ */ public class FlightRecorderApplicationStartup implements ApplicationStartup { - private long currentSequenceId; + private final AtomicLong currentSequenceId = new AtomicLong(0); private final Deque currentSteps; public FlightRecorderApplicationStartup() { - this.currentSequenceId = 0; - this.currentSteps = new ArrayDeque<>(); - this.currentSteps.offerFirst(0L); + this.currentSteps = new ConcurrentLinkedDeque<>(); + this.currentSteps.offerFirst(this.currentSequenceId.get()); } @Override public StartupStep start(String name) { - FlightRecorderStartupStep step = new FlightRecorderStartupStep(++this.currentSequenceId, name, - this.currentSteps.getFirst(), committedStep -> this.currentSteps.removeFirst()); - this.currentSteps.offerFirst(this.currentSequenceId); - return step; + long sequenceId = this.currentSequenceId.incrementAndGet(); + this.currentSteps.offerFirst(sequenceId); + return new FlightRecorderStartupStep(sequenceId, name, + this.currentSteps.getFirst(), committedStep -> this.currentSteps.removeFirstOccurrence(sequenceId)); } }