【深入浅出-JVM】(7):栈上分配

概念

对那些作用于不会逃逸出方法的对象,在分配内存时,不在将对象分配在堆内存中,而是将对象属性打散后分配在线程私有栈内存上,这样随着方法调用结束,栈上分配打散的对象也被回收掉,不在增加 GC 额外压力。

Java 对象分配流程

示例

循环创建1000000000一个对象,阻止栈上分配

栈上分配条件:开启逃逸分析 & 开启标量替换

JVM 参数:

  • 弃用逃逸分析(不允许判断对象是否可以逃逸出函数体)

-server -Xmx10m -Xms10m -XX:-DoEscapeAnalysis -XX:+PrintGC

使用 server 模式弃用逃逸分析(-server -XX:-DoEscapeAnalysis),设置堆空间大小10m,初始空间10m,打印 GC 日志

  • 弃用标量替换(不允许对象打散分配到栈上)

-server -Xmx10m -Xms10m -XX:+PrintGC -XX:-EliminateAllocations

以上二选一

代码:


package com.mousycoder.mycode.happy_jvm;

/**

 * @version 1.0

 * @author: mousycoder

 * @date: 2019-06-11 16:55

 */

public class OnStackTest {

    public static class User{

        public int id = 0;

        public String name = "";

    }

    public static void alloc(){

        User u = new User();

        u.id = 5;

        u.name = "mousycoder";

    }

    public static void main(String[] args) {

        long b = System.currentTimeMillis();

        for (int i = 0; i < 1000000000; i++) {

            alloc();

        }

        long e = System.currentTimeMillis();

        System.out.println(e-b);

    }

}

输出:


[GC (Allocation Failure) 7651K->5603K(9728K), 0.0003680 secs]

[GC (Allocation Failure) 7651K->5603K(9728K), 0.0003829 secs]

[GC (Allocation Failure) 7651K->5603K(9728K), 0.0003809 secs]

[GC (Allocation Failure) 7651K->5603K(9728K), 0.0003731 secs]

[GC (Allocation Failure) 7651K->5603K(9728K), 0.0003286 secs]

VisualGC:

分析:

本次发生的是 Minor GC,发生 GC 的原因是堆空间没有合适的区域能够存放数据结构导致的,堆从7651K 回收到 5603K,

原文地址:https://blog.51cto.com/10154395/2419154

时间: 2024-09-27 09:07:37

【深入浅出-JVM】(7):栈上分配的相关文章

JVM之对象分配:栈上分配 &amp; TLAB分配

1. Java对象分配流程 2. 栈上分配 2.1 本质:Java虚拟机提供的一项优化技术 2.2 基本思想: 将线程私有的对象打散分配在栈上 2.3 优点: 2.3.1 可以在函数调用结束后自行销毁对象,不需要垃圾回收器的介入,有效避免垃圾回收带来的负面影响 2.3.2 栈上分配速度快,提高系统性能 2.4 局限性: 栈空间小,对于大对象无法实现栈上分配 2.4 技术基础: 逃逸分析 2.4.1 逃逸分析的目的: 判断对象的作用域是否超出函数体[即:判断是否逃逸出函数体] //user的作用域

十、逃逸分析和栈上分配

Java堆区已经不再是对象实例分配的唯一空间,可以在堆区之外分配内存以提升效率降低频率,逃逸分析即是如此. 什么是逃逸分析? 例如: 一个成员方法的内部实例化了一个对象,如果这个对象被方法外的引用指向了,那么就发生了逃逸现象.JVM在内存分配的时候会分析其是否发生逃逸,如果未发生逃逸的,那么就直接在栈上分配内存空间,其生命周期和线程相同.(也称之为"栈上分配") 原文地址:https://www.cnblogs.com/lay2017/p/8157760.html

如何限制一个类只在堆上分配和栈上分配(StackOnly HeapOnly)

[本文链接] http://www.cnblogs.com/hellogiser/p/stackonly-heaponly.html [题目] 如何限制一个类只在堆上分配和栈上分配? [代码] C++ Code 1234567891011121314   class StackOnly { private:     void *operator new(size_t size) {}; }; class HeapOnly { public:     void destroy(); private

JVM的学习3_____逃逸分析与栈上分配

之前有提到过,为了提高GC的回收效率,对象实例的内存分配不一定必须存在于堆区中,还可采用堆外分配.而最常见的堆外分配就是采用逃逸分析筛选出未发生逃逸的对象,在栈帧中分配内存空间. 逃逸分析:就是分析出对象的作用域.当一个对象在方法体内声明后,该对象的引用被其他外部所引用时该对象就发生了逃逸,反之就会在栈帧中为对象分配内存空间. 根据逃逸分析在栈帧中分配的对象内存,不会使用GC进行垃圾回收.因为栈会随着方法的开始而创建,结束而销毁. 原文地址:https://www.cnblogs.com/xbf

栈上分配存储器的方法 alloca 抽样

声明一个局部变量,必须分配在堆栈上,但有或没有它的方法 当然,,那是 alloca 下面的代码显示了可变长度参数转换,alloca 要使用 int main(int argc, char ** argv) { char **argv2; int i,n; n=0; while(argv[n] != NULL) n++; printf("n %d\n",n); argv2 = alloca((n + 2) * sizeof(*argv)); argv2[0] = "progra

如何让类对象只在栈(堆)上分配空间?(转)

转自:http://blog.csdn.net/hxz_qlh/article/details/13135433 在C++中,类的对象建立分为两种,一种是静态建立,如A a:另一种是动态建立,如A* ptr=new A:这两种方式是有区别的. 1.静态建立类对象:是由编译器为对象在栈空间中分配内存,是通过直接移动栈顶指针,挪出适当的空间,然后在这片内存空间上调用构造函数 形成一个栈对象.使用这种方法,直接调用类的构造函数. 2.动态建立类对象,是使用new运算符将对象建立在堆空间中.这个过程分为

如何限制一个类对象只在栈(堆)上分配空间?

最近做了一道题:在C++中,为了让某个类只能通过new来创建(即如果直接创建对象,编译器将报错) 其实该问题等同于如何限制一个类对象只在栈(堆)上分配空间? 一般情况下,编写一个类,是可以在栈或者堆分配空间.但有些时候,你想编写一个只能在栈或者只能在堆上面分配空间的类.这能不能实现呢?仔细想想,其实也是可以滴. 在C++中,类的对象建立分为两种,一种是静态建立,如A a:另一种是动态建立,如A* ptr=new A:这两种方式是有区别的. 1.静态建立类对象:是由编译器为对象在栈空间中分配内存,

深入浅出 JVM GC(4)常用 GC 参数介绍

# 前言 从前面的3篇文章中,我们分析了5个垃圾收集器,还有一些 GC 的算法,那么,在 GC 调优中,我们肯定会先判断哪里出现的问题,然后再根据出现的问题进行调优,而调优的手段就是 JVM 提供给我们的那些参数或者说选项,这些参数将会改变 GC 的运行方式.因此,他们显得极为重要. 我们将每一个垃圾收集器相关的参数一个一个娓娓道来,注意,楼主推荐一个小程序:前阿里 JVM 大神寒泉子的公众号里面有个小程序------JVM Pocket,这个小程序介绍了所有的 JVM 参数的作用,你可以在里面

JVM的栈内存

目录 JVM栈之局部变量表:包含参数和局部变量 JVM栈之操作数栈 JVM栈之栈上分配(动态链连接) 每当启动一个新线程时,Java虚拟机都会为它分配一个Java栈.Java栈以帧为单位保存线程的运行状态.虚拟机只会直接对Java栈执行两种操作:以帧为单位的压栈和出栈. 某个线程正在执行的方法被称为该线程的当前方法,当前方法使用的栈帧称为当前帧,当前方法所属的类称为当前类,当前类的常量池称为当前常量池.在线程执行一个方法时,它会跟踪当前类和当前常量池.此外,当虚拟机遇到栈内操作指令时,它对当前帧