5

I am trying to get the caller class and method name inside a function in a Scala app. I am currently making use of the stack trace, but the performance has decreased. I am doing something like

stackTrace(CodeDepth).getClassName
stackTrace(CodeDepth).getMethodName

I have found the Java reflection to be a lot more faster, but i can only get the class name with

sun.reflect.Reflection.getCallerClass(CodeDepth).getName()

Is there a way to get the method name (and optionally the line number) via reflection? Maybe using Scala's reflection?

Thanks

sebi
  • 1,791
  • 3
  • 25
  • 43
  • I think this is what you are looking for: http://docs.oracle.com/javase/7/docs/api/java/lang/Throwable.html – nafas Sep 22 '15 at 15:17
  • possible duplicate of [Get callers method (java.lang.reflect.Method)](http://stackoverflow.com/questions/4024587/get-callers-method-java-lang-reflect-method) –  Sep 22 '15 at 15:36
  • @nafas No, using Throwable is expensive as well. See http://stackoverflow.com/questions/421280/how-do-i-find-the-caller-of-a-method-using-stacktrace-or-reflection for reference. – sebi Sep 22 '15 at 15:41
  • @RC the answer in your link seems to be expensive as well, as it uses a resource stream (IO) – sebi Sep 22 '15 at 15:41
  • What is CodeDepth in the code above? – user1868607 Aug 26 '18 at 18:04

2 Answers2

4

Unfortunately, there is no non-expensive method to do this. There is a Java Enhancement Proposal to add a better alternative, but this doesn't help unless you can wait until Java 9 (and it isn't guaranteed to be included anyway).

On the other hand, is this really a hotspot in your code? This should only matter if it's called in a loop, and in this case you probably can call it once and cache the result.

dk14
  • 22,206
  • 4
  • 51
  • 88
Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • Yeah, it is a hotspot. It's a framework for events that sits on top of logback in our app. I would like to know the method and line number the event was produced by before the event gets in logback, so that i can pipe it to tools like Kafka in different formats. I know logback has this info (the line number, at least) and it's pretty fast, so theoretically it is possible... – sebi Sep 23 '15 at 02:29
  • Well, logback uses stack trace https://github.com/qos-ch/logback/blob/d46efd0ebd856924a51b9638cc374687c6f438c8/logback-classic/src/main/java/ch/qos/logback/classic/spi/ILoggingEvent.java and specifically warns in documentation that "Generating the method name is not particularly fast." – Alexey Romanov Sep 23 '15 at 06:23
  • If logback already captures this info for you, you can at least avoid getting the stack trace twice by writing your own encoder which will listen to `ILoggingEvent`s http://logback.qos.ch/manual/encoders.html – Alexey Romanov Sep 23 '15 at 14:33
  • Update: it [made it into Java 9](https://docs.oracle.com/javase/9/docs/api/?java/lang/StackWalker.html)… – Holger Nov 20 '17 at 13:29
0

For Scala you can just use the sourcecode library from https://github.com/lihaoyi/sourcecode and just do something like:

def log(foo: String)(implicit line: sourcecode.Line, file: sourcecode.File) = {
  println(s"${file.value}:${line.value} $foo")
}

log("Foooooo") // sourcecode/shared/src/test/scala/sourcecode/Tests.scala:86 Fooooo
Carlos Saltos
  • 1,385
  • 15
  • 15