7

My Java application heap dump shows that a specific lambda used in my class has locked up some amount of memory and its not being released during GC.

Heap shows the specific anonymous lambda class as ParentClass$$Lambda$ID and in current case, the ID is 79(image attached). This ID does not seem to have any relation with the number of lambdas that exist in the class and hence we cannot conclude on which lambda is represented. I'm interested to point at the exact lambda expression as it helps in analyzing, fixing and testing the scenarios related.

Decompiling the class file with DJ did not help as it recreates the lambda expressions to a readable code. Let me know if any ideas on this.

enter image description here

Pavan Kumar
  • 4,182
  • 1
  • 30
  • 45
  • 2
    If a lambda expression allocates a significant amount of memory, there must be captured values in it. So inspecting the instance(s) may guide you to the information, which actual lambda expression it is. Further you may profile the *allocations* to find the source… – Holger Jun 19 '15 at 10:01
  • @Holger I need to be more precise here. This class has multiple lambdas meant of different purposes of similar kind. I'll depict in simple terms - say I have methods getAccountName, getAccountBalance, getAccountNominee etc - assume each of these make calls to web services on different servers and responses will be given back to other methods for processing without retaining the state. Problem here is that one of the services is taking infinite time and both service and my application do not have timeout which keeps "DefaultHttpClient"(line) as live object. So no way to identify which lambda. – Pavan Kumar Jun 19 '15 at 10:33
  • 2
    besides looking at its properties (captured values and args) in the form of outgoing references you could also look at incoming references, i.e. things that hold onto the lambda. that should usually be enough to find it – the8472 Jun 19 '15 at 10:43
  • 1
    if your profiler has allocation recording you could also use that, that should give you the callsite with linenumbers where the lambda has been allocated. – the8472 Jun 19 '15 at 10:52
  • I use jmap to collect the dump and jvisualvm to analyze. Does not seem like jvisualvm has such analysis details. Do you recommend any other tools? – Pavan Kumar Jun 19 '15 at 18:51
  • 1
    @Pavan Kumar: that’s a strange way to do it as JVisualVM can collect heap dumps directly. It’s profiler is also capable of tracking allocation sites. Don’t ask for other tools when you aren’t really using the tool you have. – Holger Jun 22 '15 at 08:07
  • @Holger Agreed that JVisualVM can connect and collect the detailed statistics, but my app runs on a server and I take dumps after few load tests and analyze and compare dumps at a later stage. – Pavan Kumar Jun 22 '15 at 14:59

1 Answers1

5

Try defining the system property

jdk.internal.lambda.dumpProxyClasses=/path/to/dir

when invoking the JVM. This will cause the runtime to write the dynamically generated lambda classes to disk, where you can inspect them with javap. This will enable you to see what fields (captured variables) they hold, and what lambda body method the lambda corresponds to.

Brian Goetz
  • 90,105
  • 23
  • 150
  • 161
  • 1
    Not much documentation is available on this except https://bugs.openjdk.java.net/browse/JDK-8023524 - though might not be a solution across JDKs. I'll give a try and let you know. – Pavan Kumar Jun 19 '15 at 18:49
  • Good solution, hope something generic(not specific to a jvm) exists in a similar fashion. – Pavan Kumar Jun 22 '15 at 05:42
  • 1
    @Pavan Kumar: since the whole existence of these classes is JVM-specific there can’t be an option to dump them that is not JVM-specific… – Holger Jun 22 '15 at 08:05
  • I can't seem to figure out how to run the javap. it does not want to run on the class i give it. Says. Error: class not found: – mhstnsc Jan 19 '18 at 15:05