jvm的内部细节

今天一家公司笔试竟问我jvm的内部细节的问题,好多都不知道,尽管复习了。我对自己有点失望,这么久了,之前从没想到了解jvm到底怎么回事儿。面试的一个问题,涉及到java String的==,何时true,何时false,以及String.intern。String.intern我还都不知道呢。

网上找了个https://www.cnblogs.com/lfs2640666960/p/9297176.html,从而得知jvm有字符串池,以及String.intern是个native函数。

那里的https://tech.meituan.com/2014/03/06/in-depth-understanding-string-intern.html我读的相当详细,至少第一部分。

那个的确写的很好,还包含intern函数的C代码,里面的确看到被intern的字符串存在类似于hashmap的数据结构里。

他给了一个很好的代码例子,其为

static final int MAX = 1000 * 10000;
static final String[] arr = new String[MAX];

public static void main(String[] args) throws Exception {
    Integer[] DB_DATA = new Integer[10];
    Random random = new Random(10 * 10000);
    for (int i = 0; i < DB_DATA.length; i++) {
        DB_DATA[i] = random.nextInt();
    }
	long t = System.currentTimeMillis();
    for (int i = 0; i < MAX; i++) {
        //arr[i] = new String(String.valueOf(DB_DATA[i % DB_DATA.length]));
         arr[i] = new String(String.valueOf(DB_DATA[i % DB_DATA.length])).intern();
    }

	System.out.println((System.currentTimeMillis() - t) + "ms");
    System.gc();
}

可以看到被注释掉的没有调用intern,运行区别为

WechatIMG2655WechatIMG2656

因为是mod 10,前十个被intern了,之后的就会自动通过哈希那个字符串常量发现已经在字符串线程池里,就直接指向它而不创建新的对象在堆上。

1345而不是10是因为那个计数包括所有静态String,就是一个空的jvm程序就会有1335个。

还有一点给我留下印象的是那新区有eden区和两个survivor区,然后才是老区。垃圾回收后生存下去的先从eden到survivor,然后survivor互相之间交换,直到survivor满或者对象生存次数达到MaxTenuringThreshold阈值。

来自 https://stackoverflow.com/questions/13543468/maxtenuringthreshold-how-exactly-it-works

Each object in Java heap has a header which is used by Garbage Collection (GC) algorithm. The young space collector (which is responsible for object promotion) uses a few bit(s) from this header to track the number of collections object that have survived (32-bit JVM use 4 bits for this, 64-bit probably some more).

During young space collection, every single object is copied. The Object may be copied to one of survival spaces (one which is empty before young GC) or to the old space. For each object being copied, GC algorithm increases it’s age (number of collection survived) and if the age is above the current tenuring threshold it would be copied (promoted) to old space. The Object could also be copied to the old space directly if the survival space gets full (overflow).

The journey of Object has the following pattern:

allocated in eden

copied from eden to survival space due to young GC

copied from survival to (other) survival space due to young GC (this could happen few times)

promoted from survival (or possible eden) to old space due to young GC (or full GC)

the actual tenuring threshold is dynamically adjusted by JVM, but MaxTenuringThreshold sets an upper limit on it.

If you set MaxTenuringThreshold=0, all objects will be promoted immediately.

I have few articles about java garbage collection, there you can find more details.

还可以参考https://www.jianshu.com/p/3d3fc356e31c

还有不同的垃圾回收算法可以通过jvm的一个开头为XX的参数选择并调,这些我之后应该也会读读相关资料的。

运行却未显示认识XX的参数

$ java -X
    -Xmixed           混合模式执行 (默认)
    -Xint             仅解释模式执行
    -Xbootclasspath:<用 : 分隔的目录和 zip/jar 文件>
                      设置搜索路径以引导类和资源
    -Xbootclasspath/a:<用 : 分隔的目录和 zip/jar 文件>
                      附加在引导类路径末尾
    -Xbootclasspath/p:<用 : 分隔的目录和 zip/jar 文件>
                      置于引导类路径之前
    -Xdiag            显示附加诊断消息
    -Xnoclassgc       禁用类垃圾收集
    -Xincgc           启用增量垃圾收集
    -Xloggc:    将 GC 状态记录在文件中 (带时间戳)
    -Xbatch           禁用后台编译
    -Xms        设置初始 Java 堆大小
    -Xmx        设置最大 Java 堆大小
    -Xss        设置 Java 线程堆栈大小
    -Xprof            输出 cpu 配置文件数据
    -Xfuture          启用最严格的检查, 预期将来的默认值
    -Xrs              减少 Java/VM 对操作系统信号的使用 (请参阅文档)
    -Xcheck:jni       对 JNI 函数执行其他检查
    -Xshare:off       不尝试使用共享类数据
    -Xshare:auto      在可能的情况下使用共享类数据 (默认)
    -Xshare:on        要求使用共享类数据, 否则将失败。
    -XshowSettings    显示所有设置并继续
    -XshowSettings:all
                      显示所有设置并继续
    -XshowSettings:vm 显示所有与 vm 相关的设置并继续
    -XshowSettings:properties
                      显示所有属性设置并继续
    -XshowSettings:locale
                      显示所有与区域设置相关的设置并继续

-X 选项是非标准选项, 如有更改, 恕不另行通知。


以下选项为 Mac OS X 特定的选项:
    -XstartOnFirstThread
                      在第一个 (AppKit) 线程上运行 main() 方法
    -Xdock:name=<应用程序名称>"
                      覆盖停靠栏中显示的默认应用程序名称
    -Xdock:icon=<图标文件的路径>
                      覆盖停靠栏中显示的默认图标

man java也没有啊

然后百度了一下达到了https://blog.csdn.net/leo187/article/details/88920036

之后或许添加更多内容在这里!

Advertisements