diff --git a/actor-typed/src/main/mima-filters/2.0.x.backwards.excludes/remove-deprecated-methods.excludes b/actor-typed/src/main/mima-filters/2.0.x.backwards.excludes/remove-deprecated-methods.excludes index c301da7df2..16fc80b4ab 100644 --- a/actor-typed/src/main/mima-filters/2.0.x.backwards.excludes/remove-deprecated-methods.excludes +++ b/actor-typed/src/main/mima-filters/2.0.x.backwards.excludes/remove-deprecated-methods.excludes @@ -18,3 +18,4 @@ # Remove deprecated methods ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.actor.typed.javadsl.TimerScheduler.startPeriodicTimer") ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.actor.typed.scaladsl.TimerScheduler.startPeriodicTimer") +ProblemFilters.exclude[MissingClassProblem]("org.apache.pekko.actor.typed.internal.LoggerClass$TrickySecurityManager") diff --git a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/internal/LoggerClass.scala b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/internal/LoggerClass.scala index a62e0b350a..555c738550 100644 --- a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/internal/LoggerClass.scala +++ b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/internal/LoggerClass.scala @@ -13,12 +13,11 @@ package org.apache.pekko.actor.typed.internal -import scala.annotation.nowarn import scala.util.control.NonFatal import org.apache.pekko import pekko.annotation.InternalApi -import pekko.util.OptionVal +import pekko.util.{ ClassContext, OptionVal } /** * INTERNAL API @@ -26,19 +25,12 @@ import pekko.util.OptionVal @InternalApi private[pekko] object LoggerClass { - // just to get access to the class context - @nowarn("msg=deprecated") - private final class TrickySecurityManager extends SecurityManager { - def getClassStack: Array[Class[_]] = getClassContext - } - private val defaultPrefixesToSkip = List("scala.runtime", "org.apache.pekko.actor.typed.internal") /** * Try to extract a logger class from the call stack, if not possible the provided default is used */ def detectLoggerClassFromStack(default: Class[_], additionalPrefixesToSkip: List[String] = Nil): Class[_] = { - // TODO use stack walker API when we no longer need to support Java 8 try { def skip(name: String): Boolean = { def loop(skipList: List[String]): Boolean = skipList match { @@ -51,7 +43,7 @@ private[pekko] object LoggerClass { loop(additionalPrefixesToSkip ::: defaultPrefixesToSkip) } - val trace = new TrickySecurityManager().getClassStack + val trace = ClassContext.getClassStack var suitableClass: OptionVal[Class[_]] = OptionVal.None var idx = 1 // skip this method/class and right away while (suitableClass.isEmpty && idx < trace.length) { diff --git a/actor/src/main/java/org/apache/pekko/util/ClassContext.java b/actor/src/main/java/org/apache/pekko/util/ClassContext.java new file mode 100644 index 0000000000..d47d638ae5 --- /dev/null +++ b/actor/src/main/java/org/apache/pekko/util/ClassContext.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.pekko.util; + +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Stream; +import org.apache.pekko.annotation.InternalApi; + +/** INTERNAL API */ +@InternalApi +public final class ClassContext { + private ClassContext() { + throw new UnsupportedOperationException("Cannot instantiate utility class"); + } + + private static final Set OPTIONS = + Set.of(StackWalker.Option.RETAIN_CLASS_REFERENCE, StackWalker.Option.SHOW_HIDDEN_FRAMES); + + private static final Function, Class[]> CLASS_STACK_WALKER = + frames -> frames.map(StackWalker.StackFrame::getDeclaringClass).toArray(Class[]::new); + + public static Class[] getClassStack() { + return StackWalker.getInstance(OPTIONS).walk(CLASS_STACK_WALKER); + } +} diff --git a/bench-jmh/src/main/scala/org/apache/pekko/util/StackBench.scala b/bench-jmh/src/main/scala/org/apache/pekko/util/StackBench.scala deleted file mode 100644 index d427426785..0000000000 --- a/bench-jmh/src/main/scala/org/apache/pekko/util/StackBench.scala +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * license agreements; and to You under the Apache License, version 2.0: - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * This file is part of the Apache Pekko project, which was derived from Akka. - */ - -/* - * Copyright (C) 2009-2022 Lightbend Inc. - */ - -package org.apache.pekko.util - -import java.util.concurrent.TimeUnit -import scala.annotation.nowarn - -import org.openjdk.jmh.annotations.{ Benchmark, Measurement, Scope, State } - -@State(Scope.Benchmark) -@Measurement(timeUnit = TimeUnit.MICROSECONDS) -class StackBench { - - @nowarn("msg=deprecated") - class CustomSecurtyManager extends SecurityManager { - def getTrace: Array[Class[_]] = - getClassContext - } - - @Benchmark - def currentThread(): Array[StackTraceElement] = { - Thread.currentThread().getStackTrace - } - - @Benchmark - def securityManager(): Array[Class[_]] = { - (new CustomSecurtyManager).getTrace - } - -}