From ea3fe95881ba0298a23590b875db417bdec01bbf Mon Sep 17 00:00:00 2001 From: GGGGGHT Date: Wed, 13 Jul 2022 15:31:42 +0800 Subject: [PATCH 1/2] Use StackWalker to deduce main application class See gh-31701 --- .../boot/SpringApplication.java | 17 ++++------- .../boot/SpringApplicationTests.java | 30 +++++++++++++++++++ 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java index e59fa6bf69..09be887a52 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java @@ -25,6 +25,7 @@ import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Properties; import java.util.Set; import java.util.stream.Collectors; @@ -274,18 +275,10 @@ public class SpringApplication { } private Class deduceMainApplicationClass() { - try { - StackTraceElement[] stackTrace = new RuntimeException().getStackTrace(); - for (StackTraceElement stackTraceElement : stackTrace) { - if ("main".equals(stackTraceElement.getMethodName())) { - return Class.forName(stackTraceElement.getClassName()); - } - } - } - catch (ClassNotFoundException ex) { - // Swallow and continue - } - return null; + return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE) + .walk((s) -> s.filter(e -> Objects.equals(e.getMethodName(), "main")).findFirst() + .map(StackWalker.StackFrame::getDeclaringClass)) + .orElse(null); } /** diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java index 5326bddcb4..022c4d3301 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java @@ -23,6 +23,7 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; @@ -1314,6 +1315,35 @@ class SpringApplicationTests { .accepts(hints); } + @Test + void deduceMainApplicationClass() { + assertThat( + Objects.equals(deduceMainApplicationClassByStackWalker(), deduceMainApplicationClassByThrowException())) + .isTrue(); + } + + private Class deduceMainApplicationClassByThrowException() { + try { + StackTraceElement[] stackTrace = new RuntimeException().getStackTrace(); + for (StackTraceElement stackTraceElement : stackTrace) { + if ("main".equals(stackTraceElement.getMethodName())) { + return Class.forName(stackTraceElement.getClassName()); + } + } + } + catch (ClassNotFoundException ex) { + // Swallow and continue + } + return null; + } + + private Class deduceMainApplicationClassByStackWalker() { + return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE) + .walk((s) -> s.filter(e -> Objects.equals(e.getMethodName(), "main")).findFirst() + .map(StackWalker.StackFrame::getDeclaringClass)) + .orElse(null); + } + private ArgumentMatcher isAvailabilityChangeEventWithState( S state) { return (argument) -> (argument instanceof AvailabilityChangeEvent) From 38fedcff34e4047e65560e3f8c91f8c5c84e61d6 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 20 Jul 2022 12:44:58 +0100 Subject: [PATCH 2/2] Polish "Use StackWalker to deduce main application class" See gh-31701 --- .../boot/SpringApplication.java | 12 ++++++-- .../boot/SpringApplicationTests.java | 30 ------------------- 2 files changed, 9 insertions(+), 33 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java index 09be887a52..d7adbea769 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java @@ -16,6 +16,7 @@ package org.springframework.boot; +import java.lang.StackWalker.StackFrame; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; @@ -26,9 +27,11 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Properties; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -275,12 +278,15 @@ public class SpringApplication { } private Class deduceMainApplicationClass() { - return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE) - .walk((s) -> s.filter(e -> Objects.equals(e.getMethodName(), "main")).findFirst() - .map(StackWalker.StackFrame::getDeclaringClass)) + return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).walk(this::findMainClass) .orElse(null); } + private Optional> findMainClass(Stream stack) { + return stack.filter((frame) -> Objects.equals(frame.getMethodName(), "main")).findFirst() + .map(StackWalker.StackFrame::getDeclaringClass); + } + /** * Run the Spring application, creating and refreshing a new * {@link ApplicationContext}. diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java index 022c4d3301..5326bddcb4 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java @@ -23,7 +23,6 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; @@ -1315,35 +1314,6 @@ class SpringApplicationTests { .accepts(hints); } - @Test - void deduceMainApplicationClass() { - assertThat( - Objects.equals(deduceMainApplicationClassByStackWalker(), deduceMainApplicationClassByThrowException())) - .isTrue(); - } - - private Class deduceMainApplicationClassByThrowException() { - try { - StackTraceElement[] stackTrace = new RuntimeException().getStackTrace(); - for (StackTraceElement stackTraceElement : stackTrace) { - if ("main".equals(stackTraceElement.getMethodName())) { - return Class.forName(stackTraceElement.getClassName()); - } - } - } - catch (ClassNotFoundException ex) { - // Swallow and continue - } - return null; - } - - private Class deduceMainApplicationClassByStackWalker() { - return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE) - .walk((s) -> s.filter(e -> Objects.equals(e.getMethodName(), "main")).findFirst() - .map(StackWalker.StackFrame::getDeclaringClass)) - .orElse(null); - } - private ArgumentMatcher isAvailabilityChangeEventWithState( S state) { return (argument) -> (argument instanceof AvailabilityChangeEvent)