These occupies space in heap
String: wise use of String, try to use as local variables, make sure that there are no string without references and try to use StringBuffer or StringBuilder
static: wise use of static
Instance variables: try to declare variables locally as far as possible
objects: reuse as far as possible
Please correct me if so far I am wrong…also suggest any more precautions that I can take to reduce the usage of Heap开发者_如何学运维 space while programming in Java
You need to be more specific about what you are trying to achieve. There are two goals that are (in some cases) contradictory:
- minimizing the number of objects that are allocated, and hence the number of times the GC runs,
- minimizing the amount of heap space that is used for live objects, and hence the "footprint" of your application.
static: wise use of static
This is meaningless advice, unless you say what "wise use" is.
String: wise use of String, try to use as local variables, make sure that there are no string without references and try to use StringBuffer or StringBuilder
- Wise use is meaningless advice; see above.
- Making sure there are no strings without references is meaningless because every string has a reference.
- Trying to use local variables is useful, but not always applicable. Sometimes using a static or instance variable could reduce the number of times you create new strings. Sometimes assigning an intermediate string to a local variable could increase its lifetime.
- You shouldn't use StringBuffer for string assembly.
- There are many cases where using a StringBuilder in string assembly does not help, and just makes the code harder to read. In general StringBuilder should only be used if you can't do the string assembly in one expression.
Instance variables: try to declare variables locally as far as possible
This is sound advice generally, though it needs to be balanced with other things.
objects: reuse as far as possible
This is bad advice.
Reuse "as far as possible" means object pools, and object pools tend to use more heap space than if you just dropped the object and let the GC reclaim it. Object pools should only be used if it is critical that you minimize the object creation rate. Even then you need to be very careful to avoid:
- leaking objects by not returning them to the pool
- issuing "dirty" objects from the pool
- bugs as a result of the extra complexity, and
- wasting memory (e.g. on the pool data structures, and idle objects in the pool) and therefore making the GC run more often.
Here are a couple of points that can help to improve an application's memory utilization if used wisely. But please note that they are not universally applicable, and if you don't understand what you are doing you can get a bad outcome .... a significantly more complex program and little if any improvement in memory usage.
Design / choose your collection data structures carefully
Many of the standard Java collection types are rather memory hungry. For example, an ArrayList<Integer>
consists of 2 objects to start out, and an extra object for each array element (depending on how the elements are created ...). In addition, the ArrayList
's backing array may be larger than it needs to be. By contrast, an int[]
consists of just one object, and uses just one 32-bit word per element.
(A similar comparison can be made for more complex data structures, especially when the base type is a primitive type. There 3rd-party libraries that implement this kind of stuff; e.g. the GNU Trove libraries.)
It is clear that if you design your data structures carefully you can represent them using less memory and fewer objects.
However, the flip-side is that this tends to make your application more complicated and harder to maintain. For instance:
Using an
int[]
instead of anArrayList<Integer>
results in more exposure of implementation details, and increased coupling.Using arrays to represent lists of variable or uncertain size is tricky.
Lots of APIs are designed to take
List
orCollection
parameters rather than array parameters. So you are more likely to have to develop your own custom non-Collection versions of library code.Generics and arrays don't mix well.
In summary, while you can save heap space, you are likely to end up paying in other ways.
Use Mutable Classes
Instances of classes like String
and BigInteger
are immutable by design. This simplifies the computational model, but it means that "changing" something involves creating new objects. You can often reduce memory usage by:
using mutable versions of the types; e.g. using a
StringBuilder
/StringBuffer
instead of aString
, ormaking your own application data classes mutable rather than immutable.
Once again, there is a flip-side. Mutable data structures can lead to more complexity; e.g. if your application is multi-threaded, or if you need to be able to undo things to backtrack or because some step failed. This makes your application more complex. In some cases, the only viable solution is to copy the data structure, resulting in using more memory.
In summary, while you can save heap space, you may well end up paying in other ways. And you may not even save memory in the end.
That's pretty good. One other thing to look out for is proper closing of your Buffer type objects, by that I mean Sockets, FileReaders, etc... Make sure that you wrap them in try finally where in the finally you remember to flush (if necessary) and close the connection/buffer. This avoids stray resources being held because the underlying connection would still be active.
Also on the subject of Strings, always intern()
them when reading from a file or database so you don't end up with duplicate char arrays.
First: measure which objects really take up the most heap space: jmap -histo:live
Then try to reduce the top five classes. Nothing more. Measure again. Repeat until you are satisified.
If one of the candidates is HashMap
or HashSet
or ConcurrentHashMap
: these classes waste heap memory as they can. Use memory-efficient alternatives for them.
精彩评论