Thanks for the great info, Ben. One thing that occurred to me is that while delegates or lambdas would solve this problem, they do seem to go along with the .NET way of doing things: giving developers explicit control over memory allocation, similar to how .NET has an explicit "struct" construct in order to ensure stack allocation. We theoretically get a stack allocation in Java as well, but only by way of runtime optimizations. In other words, the language presents an illusion to the developer about certain simplicities of syntax and logic and allows the JVM to do some heavy lifting. There are obviously some serious challenges for engineers working on the JVM's, and it can occasionally be frustrating to developers to not have that fine-grained control over runtime, but I think in the long run, we've seen this approach to be a beneficial (a la garbage collection evolution).
In the case of these stateless anonymous inner classes, I thought for sure it would fall into the same set of optimization targets as escape analysis. I think stack allocation might be helpful as an optimization, but ultimately turning such an object into a lambda seems the way to go, since there are situations, where an object will be shared across threads, but is stateless nonetheless. It will be interesting to see how this issue develops with JDK 7 and 8 language changes. Alexey ________________________________ From: Ben Schulz <[email protected]> To: The Java Posse <[email protected]> Sent: Fri, April 29, 2011 9:26:20 AM Subject: [The Java Posse] Re: question about JVM optimizations and instantiating stateless "function" objects To answer the original question: No there is no such optimization. Theoretically it can be optimized if the JIT can prove that the object's identity is irrelevant (necessary due to[1]). Since you need escape analysis for that, the JIT might as well just determine that the object does not escape and stack allocate it. However, at this point, objects that ArgEscape[2] still get heap allocated[3] (this information is somewhat old, but afaik still accurate). Anyways, this is one of the great things about lambdas: They won't be instanciated via instance creation expressions and thus can be made static without performing (successful) escape analysis. With kind regards Ben [1] http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#23747 [2] http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.37.3797 [3] http://wikis.sun.com/display/HotSpotInternals/EscapeAnalysis On 28 Apr., 19:52, Alexey Zinger <[email protected]> wrote: > As I was looking at some code today that used FP concepts with Guava (Google > Collections), I saw the same pattern I see over and over in such Java code that > strives to be expressive in a functional manner: a function is required as a > parameter for some operation and it so happens that the code that sends that > function along instantiates the Guava Function object (or something similar, > like Comparator) there and then. The look of the code is as close to what we > can expect to see in a "true" functional language with current Java > capabilities, but more often than not, the purpose of including the guts of the > function right there is to bundle the function definition with its logical > context, not because we really need to instantiate the object in that place. > In > fact, typically, the anonymous inner class expressing said function always > produces identical instances. Here's a hypothetical example. Let's assume the > following gets called a lot throughout the uptime of the program: > > final List<String> lowerCaseList = ...; > final List<String> upperCaseList = Lists.transform(lowerCaseList, new > Function<String, String>() { > public String apply(String s) { return s.toUpperCase(); } > > }); > > This is quite readable, but in theory, the following would be more efficient: > > final List<String> lowerCaseList = "..."; > final List<String> upperCaseList = Lists.transform(lowerCaseList, > toUpperFunction); > > where toUpperFunction is defined elsewhere, ensuring a more appropriate >lifespan > to the instance. Is there a JVM optimization that developers can reasonably > rely on, that would effectively promote this particular apply(String) > implementation to a "static" level, so that no instance memory would need to be > allocated and reclaimed, and no constructor would need to be called? And if > not, is this on the order of magnitude, where it's generally not a concern in > performance-sensitive scenarios? > > Alexeyhttp://azinger.blogspot.comhttp://bsheet.sourceforge.nethttp://wcollage.sourceforge.net >t -- You received this message because you are subscribed to the Google Groups "The Java Posse" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/javaposse?hl=en. -- You received this message because you are subscribed to the Google Groups "The Java Posse" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.
