How can I detect/avoid autoboxing in Java?
Asked Answered
D

3

8

I'm working on a program that deals constantly with gigabytes of data, mostly primitives and strings. I need to avoid having the primitives converted to Objects by autoboxing as this explodes the heap size and GC-time.

Currently, I make changes and run the code in VisualVM and see I have millions of extra Integers or Shorts, or Objects. Then I step through the code in a debugger into my libraries and JDK classes to find where the boxing occurs. Is there tooling to help with this?

I use Intellij as my IDE. In Intellij, you can use an inspection to find the auto-boxing in your own code, but it doesn't seem to extend to library code. To do so, select from the menu:

Analyzye >> Run Inspection by Name...

Then type in 'auto' at the prompt. An auto-boxing inspection should appear for selection.

However, at this point, I have removed essentially all auto-boxing from my own code. What I need is to be able to find out when i pass a primitive into a library method, is the library code auto-boxing the primitive at any point.

Doctrinaire answered 19/3, 2016 at 23:32 Comment(7)
When dealing with amounts of data, where autoboxing becomes an issue, Java might not be the right language for your application. Consider using c or c++. Alternatively you could write a program in c that processes your data and then display the results inside your Java application.Cushat
have you tried findbugs ?Guarantor
I found this related question that contains some useful suggestions. #15819375Doctrinaire
I'd have to agree with @MarioDekena - it doesn't sound like java is the right tool for your needs. Depending on your data source and format you should consider C++ or javascript. Perhaps even take a look at Go.Pawn
Something I've seen that results in the creation of many Integer objects is doing math with them. Integer sum = 0; for (int value : values) sum += value; is legal code, but will create an additional Integer object for every member of values.Colourable
"converted to Objects by autoboxing as this explodes the heap size and GC-time." ... you may be reacting to a problem that you don't have. If you have profiled your code and you can't demonstrate a performance or memory problem that may be related to excessive object creation, then even if you are inadvertently boxing primitives here and there, the net impact on your code will be marginal. I respectfully suggest that you report on your profiling results before you begin any large scale rehash of your code.Bruch
@Bruch Um, yeah. It's a problem I do have. Thanks for the tip.Doctrinaire
O
1

You should look trough your code for any references to Integer, Double etc... Should be easily done with Eclipse or IntelliJ. Do you maybe hold lots of data in Javas build in Maps, Collections etc, with primitive type wrappers that are autoboxed due to generics?

A good way to get rid of this is to use GNU Trove instead of javas built in datastructures: http://trove4j.sourceforge.net/html/overview.html. In provides Maps and Collections that use primitive types instead of generics and reduces memory usage.

Another culprit for creating a lot of object instances could be usage of the InvocationHandler interface. This thing creates an array of Objects for in parameters to methods each time a method is invoked. Proxy objects often make use of this. Do you maybe have third party libs or own code that does this?

Lastly, use a profiler that can show object instances hierarchically. I think VisualVM does this, not sure.

You shouldn't have to resort to C++ as suggested by some. You can design around it.

Orthopter answered 20/3, 2016 at 0:23 Comment(2)
Thanks. I use the fastuti library fastutil.di.unimi.it, which is like Trove. I'll have to look into InvocationHandler.Doctrinaire
There are better options than Trove: java-performance.info/…Scallion
I
1

It should be possible to write a simple javaagent that adds logging for valueOf calls (Integer.valueOf) All you need for this task is byte code manipulation library such as Javassist

Inexistent answered 20/3, 2016 at 17:37 Comment(3)
Is that how all boxing is performed? I assumed that if you pass int i to method foo(Integer i), the boxing was handled directly by the compilerDoctrinaire
Afaik it's always done using valueOf. I'll see, if I can find some evidence with this tiny mobile screen :-)Inexistent
#409161Inexistent
O
0

Assuming you have the source of the libraries you are using, how about using Structural Search & Replace? Use the Copy existing template... button in the Structural Search & Replace dialog and select boxed expressions. This will find all places where expressions are (not explicitly) boxed.

Search in scope Project and Libraries to search everywhere or create a custom scope with for example a pattern like lib:omg.a.package..* to search in that package only.

Owain answered 20/3, 2016 at 20:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.