티스토리 뷰
https://medium.com/javarevisited/basic-memory-saving-techniques-for-java-programming-6677a7237a69
위 글을 번역하면서, 조금씩 내용을 추가했다.
1. 프리미티브 타입(primitive type)을 사용하자
Integer x = 42; => int x = 42;
Double d = 3.14; => double d = 3.14;
Boolean b = true; => boolean b = true;
Integer, Double, Boolean과 같은 프리미티프 타입을 Wrapping한 Object들을 사용하면 불필요한 오버헤드를 만들 수 있으니, 사용을 피하는게 좋다.
2. 스트링을 결합할 때 StringBuilder를 사용하자
String s = "Hello" + " World";
대신에 아래를 권장한다.
StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(" World");
String s = sb.toString();
사실 하나만 결합할 경우 큰 차이를 못 느낄 것이다. 하지만 내부 동작 과정을 확인하고, 다중으로 도는 것을 보면 왜 그런지 알 수 있을 것이다.
String a = "";
for(int i = 0; i < 10000; i++) {
a = a + i;
}
--> 위와 같이 작성하면, 아래와 같이 동작한다.
String b = "";
for(int i = 0; i < 10000; i++) {
b = new StringBuilder(b).append(i).toString();
}
StringBuilder를 쓰라는 이유가 있다.
이것도 자바 9버전부터 컴파일러가 자동으로 변환해주게 변경된 거라 9버전 이하의 자바를 사용 중이라면 성능 차이는 더 커질 것이다.
StringBuilder로 구현하면 차이를 확실히 알 수 있다.
final StringBuilder a = new StringBuilder();
for(int i = 0; i < 10000; i++) {
a.append(i);
}
final String b = a.toString();
훨씬 간결하게 정리된다.
3. lazy 초기화를 사용하자
이건 나도 처음 듣는 방법인데, 생각보다 괜찮은 방식인 것 같다.
private List<String> myList;
public List<String> getMyList() {
if (myList == null) {
myList = new ArrayList<>();
}
return myList;
}
클래스가 로드될 때 목록 개체를 초기화하는 대신 지연 초기화를 사용하여 실제로 필요할 때까지 개체 생성이 지연된다.
이렇게 하면 불필요한 개체 생성을 방지하여 메모리를 절약할 수 있다고 한다.
4. 배열의 크기가 명확할 때는 초기화해서 사용하자
ArrayList도 좋은 컬렉션이지만, 문자열의 크기를 알고 있을 때는 Array를 사용하는게 좋다고 한다.
String[] array = new String[1000];
5. Object를 재사용하자
List<String> tempList = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
tempList.add("Item " + i);
// do something with tempList
}
tempList.clear(); // clear the list for reuse
for (int i = 0; i < 1000; i++) {
tempList.add("Another item " + i);
// do something with tempList
}
좀 귀찮은 방법이긴 하지만, 리스트를 새로 만들지 않고 재사용하면 메모리 절약을 할 수 있다.
6. 정적 팩토리 매서드를 사용하자
public static List<String> getList() {
return new ArrayList<>(1000); // specify the initial capacity
}
매번 새로운 ArrayList를 만드는 것보다 특정한 크기의 ArrayList를 사용하는 것이 메모리 절약에 도움을 준다고 한다.
7. flyweight 패턴을 사용하자
Map<String, String> map = new HashMap<>();
String key = "myKey";
String value = "myValue";
map.put(key, value);
String anotherValue = map.get(key); // reuse the same object instead of creating a new one
String 에 새 문자열을 할당하는 것보다 기존에 사용하던 객체를 공유하는 것이 메모리 절약에 도움을 준다고 한다.
8. intern() 매서드를 사용하자
String s1 = "hello";
String s2 = "hello". Intern();
intern()을 사용하면 동일한 문자열이 여러 번 생성되더라도 문자열 인스턴스 하나만 생성되도록 한다. 이렇게 하면 생성되는 문자열 객체의 수를 줄여 메모리를 절약할 수 있다.
9. 불필요한 autoboxing을 피하자
int a = 10;
Integer b = a; // 오토박싱
int c = b; // 오토언박싱
위의 경우가 오토박싱/언박싱이다. 이렇게 쓰지말고, 아래와 같이 valueOf 매서드를 쓰면 메모리를 절약할 수 있다고 한다.
int i = 42;
Integer j = Integer.valueOf(i); // use Integer.valueOf() instead of autoboxing
10. finalize() 매서드를 주의해서 사용하자
public class MyClass {
private byte[] data = new byte[1000];
@Override
protected void finalize() throws Throwable {
super.finalize();
// clean up resources
}
}
finalize() 메서드는 호출되는 시점이 보장되지 않으며, 실행하는데 있어서 큰 오버헤드가 발생한다. 또한 finalize() 메서드가 실행되는 동안에는 객체가 다른 스레드에서도 사용할 수 없으므로 동시성 문제가 발생할 수 있다.
Java 9에서는 finalize() 메서드가 deprecated되었고, Java 11부터는 삭제되었으니, 이전 버전의 자바를 사용 중이라면 꼭 주의해야한다.
마치며
사실 메모리를 신경쓰면서 개발할거면, 개발 언어로 자바는 적합하지 않다고 생각한다. 메모리를 신경쓰면서 개발하기 좋은 언어가 요즘엔 정말 많기 때문이다.
하지만 빡빡한 상황에서 어쩔 수 없이 자바를 사용 중이라면, 위 내용이 제법 도움이 될 것 같다.
'개발 > JAVA' 카테고리의 다른 글
java.lang.UnsupportedOperationException at java.base/java.util.AbstractList.remove(AbstractList.java:167) 에러 수정하기 (0) | 2023.08.22 |
---|---|
Java에서 String에 포함된 HTML 태그 제거하기(정규식 사용 X) (0) | 2023.06.22 |
[JAVA] String vs StringBuffer vs StringBuilder (0) | 2023.03.02 |
[JAVA] Json 형태의 String에 Json Pretty Format 적용하기 (1) | 2023.02.07 |
모던 자바 인 액션(Modern Java in Action). 2장 요약 (0) | 2023.01.31 |
- Total
- Today
- Yesterday
- MySQL
- 람다
- java
- JWT
- openAI API
- Elastic cloud
- 스프링부트
- Log
- ChatGPT
- 후쿠오카
- cache
- 오블완
- Kotlin
- AWS EC2
- AWS
- Spring
- OpenAI
- EKS
- elasticsearch
- 티스토리챌린지
- CloudFront
- springboot
- OpenFeign
- terraform
- serverless
- lambda
- S3
- GIT
- docker
- AOP
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |