【Java】幾種典型的記憶體溢出案例,都在這兒了!
寫在前面
作為程式員,多多少少都會遇到一些記憶體溢出的場景,如果你還沒遇到,說明你工作的年限可能比較短,或者你根本就是個假程式員!哈哈,開個玩笑。今天,我們就以Java代碼的方式來列舉幾個典型的記憶體溢出案例,希望大家在日常工作中,盡量避免寫這些low水準的代碼。
定義主類結構
首先,我們建立一個名稱為BlowUpJVM的類,之後所有的案例實驗都是基于這個類進行。如下所示。
public class BlowUpJVM {
}
棧深度溢出
public static void testStackOverFlow(){
BlowUpJVM.testStackOverFlow();
棧不斷遞歸,而且沒有處理,是以虛拟機棧就不斷深入不斷深入,棧深度就這樣溢出了。
永久代記憶體溢出
public static void testPergemOutOfMemory1(){
//方法一失敗
List list = new ArrayList();
while(true){
list.add(UUID.randomUUID().toString().intern());
打算把String常量池堆滿,沒想到失敗了,JDK1.7後常量池放到了堆裡,也能進行垃圾回收了。
然後換種方式,使用cglib,用Class把老年代取堆滿
public static void testPergemOutOfMemory2(){
try {
while (true) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOM.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
return proxy.invokeSuper(obj, args);
}
});
enhancer.create();
}
catch (Exception e){
e.printStackTrace();
虛拟機成功記憶體溢出了,那JDK動态代理産生的類能不能溢出呢?
public static void testPergemOutOfMemory3(){
while(true){
final OOM oom = new OOM();
Proxy.newProxyInstance(oom.getClass().getClassLoader(), oom.getClass().getInterfaces(), new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(oom, args);
return result;
}
});
事實表明,JDK動态代理差生的類不會造成記憶體溢出,原因是:JDK動态代理産生的類資訊,不會放到永久代中,而是放在堆中。
本地方法棧溢出
public static void testNativeMethodOutOfMemory(){
int j = 0;
Printer.println(j++);
ExecutorService executors = Executors.newFixedThreadPool(50);
int i=0;
while(i++<10){
executors.submit(new Runnable() {
public void run() {
}
});
}
這個的原理就是不斷建立線程池,而每個線程池都建立10個線程,這些線程池都是在本地方法區的,久而久之,本地方法區就溢出了。
JVM棧記憶體溢出
public static void testStackOutOfMemory(){
while (true) {
Thread thread = new Thread(new Runnable() {
public void run() {
while(true){
}
}
});
thread.start();
}
線程的建立會直接在JVM棧中建立,但是本例子中,沒看到記憶體溢出,主機先挂了,不是JVM挂了,真的是主機挂了,無論在mac還是在windows,都挂了。
溫馨提示,這個真的會當機的。
堆溢出
public static void testOutOfHeapMemory(){
StringBuffer B = new StringBuffer();
for(int i = 0 ; i < 10000 ; i++){
B.append(i);
}
list.add(B);
不斷往堆中塞新增的StringBuffer對象,堆滿了就直接溢出了。
測試案例完整代碼
public class BlowUpJVM {
//棧深度溢出
public static void testStackOverFlow(){
BlowUpJVM.testStackOverFlow();
}
//不能引起永久代溢出
public static void testPergemOutOfMemory1(){
//方法一失敗
List<String> list = new ArrayList<String>();
while(true){
list.add(UUID.randomUUID().toString().intern());
}
}
//永久代溢出
public static void testPergemOutOfMemory2(){
try {
while (true) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOM.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
return proxy.invokeSuper(obj, args);
}
});
enhancer.create();
}
}
catch (Exception e){
e.printStackTrace();
}
}
//不會引起永久代溢出
public static void testPergemOutOfMemory3(){
while(true){
final OOM oom = new OOM();
Proxy.newProxyInstance(oom.getClass().getClassLoader(), oom.getClass().getInterfaces(), new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(oom, args);
return result;
}
});
}
}
//本地方法棧溢出
public static void testNativeMethodOutOfMemory(){
int j = 0;
while(true){
Printer.println(j++);
ExecutorService executors = Executors.newFixedThreadPool(50);
int i=0;
while(i++<10){
executors.submit(new Runnable() {
public void run() {
}
});
}
}
}
//JVM記憶體溢出
public static void testStackOutOfMemory(){
while (true) {
Thread thread = new Thread(new Runnable() {
public void run() {
while(true){
}
}
});
thread.start();
}
}
//堆溢出
public static void testOutOfHeapMemory(){
List<StringBuffer> list = new ArrayList<StringBuffer>();
while(true){
StringBuffer B = new StringBuffer();
for(int i = 0 ; i < 10000 ; i++){
B.append(i);
}
list.add(B);
}
}
寫在最後
如果覺得文章對你有點幫助,請微信搜尋并關注「 冰河技術 」微信公衆号,跟冰河學習高并發程式設計技術。
最後,附上并發程式設計需要掌握的核心技能知識圖,祝大家在學習并發程式設計時,少走彎路。
原文位址
https://www.cnblogs.com/binghe001/p/12952772.html