文档章节

Integer面试连环炮以及源码分析

胡金水
 胡金水
发布于 08/14 10:41
字数 1112
阅读 18
收藏 0
场景:

  昨天有位朋友去面试,我问他面试问了哪些问题,其中问了Integer相关的问题,以下就是面试官问的问题,还有一些是我对此做了扩展。

问:两个new Integer 128相等吗?

答:不。因为Integer缓存池默认是-127-128;

问:可以修改Integer缓存池范围吗?如何修改?

答:可以。使用-Djava.lang.Integer.IntegerCache.high=300设置Integer缓存池大小

问:Integer缓存机制使用了哪种设计模式?

答:亨元模式;

问:Integer是如何获取你设置的缓存池大小?

答:sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");

问:sun.misc.VM.getSavedPropertySystem.getProperty有啥区别?

答:唯一的区别是,System.getProperty只能获取非内部的配置信息;例如java.lang.Integer.IntegerCache.highsun.zip.disableMemoryMappingsun.java.launcher.diagsun.cds.enableSharedLookupCache等不能获取,这些只能使用sun.misc.VM.getSavedProperty获取

Integer初始化源码分析:

private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);

        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}

VM.class源码分析:

初始化:

static {
    allowArraySyntax = defaultAllowArraySyntax;
    savedProps = new Properties();
    finalRefCount = 0;
    peakFinalRefCount = 0;
    initialize();
}

getSavedProperty方法:

public static String getSavedProperty(String var0) {
    if (savedProps.isEmpty()) {
        throw new IllegalStateException("Should be non-empty if initialized");
    } else {
        return savedProps.getProperty(var0);
}    

savedProps.getProperty方法:

public String getProperty(String key) {
    Object oval = super.get(key);
    String sval = (oval instanceof String) ? (String)oval : null;
    return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
}

System.java源码分析:

/**
 * 初始化系统类。 线程初始化后调用。
 */
private static void initializeSystemClass() {

    /**
     * VM可能会调用JNU_NewStringPlatform()来在“props”初始化期间设置那些编码敏感属性(user.home,user.name,boot.class.path等),
     * 它们可能需要通过System.getProperty()进行访问, 在初始化的早期阶段已经初始化(放入“props”)的相关系统编码属性。
     * 因此,请确保初始化时可以使用“props”,并直接将所有系统属性放入其中。
     */
    props = new Properties();
    initProperties(props);  // initialized by the VM

    /**
     * 某些系统配置可以由VM选项控制,例如用于支持自动装箱的对象标识语义的最大直接内存量和整数高速缓存大小。 通常,库将获得这些值
     * 来自VM设置的属性。 如果属性是
     * 仅限内部实现使用,应从系统属性中删除这些属性。
     *
     *   请参阅java.lang.Integer.IntegerCache和
     *   例如,sun.misc.VM.saveAndRemoveProperties方法。
     *
     *   保存系统属性对象的私有副本,该副本只能由内部实现访问。 去掉
     * 某些不适合公共访问的系统属性。
     */
    sun.misc.VM.saveAndRemoveProperties(props);


    lineSeparator = props.getProperty("line.separator");
    sun.misc.Version.init();

    FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
    FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
    FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
    setIn0(new BufferedInputStream(fdIn));
    setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding")));
    setErr0(newPrintStream(fdErr, props.getProperty("sun.stderr.encoding")));

    /**
     * 现在加载zip库,以防止java.util.zip.ZipFile稍后尝试使用它来加载此库。
     */
    loadLibrary("zip");

    // 为HUP,TERM和INT(如果可用)设置Java信号处理程序。
    Terminator.setup();

    /**
     * 初始化需要为类库设置的任何错误的操作系统设置。
     * 目前,除了在使用java.io类之前设置了进程范围错误模式的Windows之外,这在任何地方都是无操作的。
     */
    sun.misc.VM.initializeOSEnvironment();

    /**
     * 主线程没有像其他线程一样添加到其线程组中; 我们必须在这里自己做。
     */
    Thread current = Thread.currentThread();
    current.getThreadGroup().add(current);

    // 注册共享秘密
    setJavaLangAccess();

    /**
     * 在初始化期间调用的子系统可以调用sun.misc.VM.isBooted(),以避免执行应该等到应用程序类加载器设置完毕的事情。
     * 重要信息:确保这仍然是最后一次初始化操作!
     */
    sun.misc.VM.booted();
}

重点看这句:sun.misc.VM.saveAndRemoveProperties(props);他会移除系统内部使用的配置,咱们来看看源码是如何操作的。

sun.misc.VM.saveAndRemoveProperties方法:

public static void saveAndRemoveProperties(Properties var0) {
    if (booted) {
        throw new IllegalStateException("System initialization has completed");
    } else {
        savedProps.putAll(var0);
        String var1 = (String)var0.remove("sun.nio.MaxDirectMemorySize");
        if (var1 != null) {
            if (var1.equals("-1")) {
                directMemory = Runtime.getRuntime().maxMemory();
            } else {
                long var2 = Long.parseLong(var1);
                if (var2 > -1L) {
                    directMemory = var2;
                }
            }
        }

        var1 = (String)var0.remove("sun.nio.PageAlignDirectMemory");
        if ("true".equals(var1)) {
            pageAlignDirectMemory = true;
        }

        var1 = var0.getProperty("sun.lang.ClassLoader.allowArraySyntax");
        allowArraySyntax = var1 == null ? defaultAllowArraySyntax : Boolean.parseBoolean(var1);
        //移除内部使用的配置,不应该让看到这些配置信息
        var0.remove("java.lang.Integer.IntegerCache.high");
        var0.remove("sun.zip.disableMemoryMapping");
        var0.remove("sun.java.launcher.diag");
        var0.remove("sun.cds.enableSharedLookupCache");
    }
}

© 著作权归作者所有

胡金水
粉丝 0
博文 2
码字总数 2011
作品 0
深圳
私信 提问
阿里社招面试应该如何准备才能事半功倍呢?

  我会分为四个部分来谈论这个问题,由于LZ本身是Java出身,因此关于主语言的问题,都是与Java相关,其它语言的同学可以选择性忽略。此外,面试的时候一般面试官的问题都是环环相扣,逐渐深...

Java高级进阶架构师
2018/07/19
0
0
参加阿里这类大公司的社招该如何准备?

引言 其实本来真的没打算写这篇文章,主要是LZ得记忆力不是很好,不像一些记忆力强的人,面试完以后,几乎能把自己和面试官的对话都给记下来。LZ自己当初面试完以后,除了记住一些聊过的知识...

kangbin825
2017/04/03
0
0
我从阿里面试回来,想和Java程序猿谈一谈

点击上方“程序员大咖”,选择“置顶公众号” 关键时刻,第一时间送达! 最近小编看了一篇关于面试的文章,题目是“我从阿里面试回来,想和Java程序员谈一谈”,内容不是讲面试前刷题,而是更...

px01ih8
2017/12/18
0
0
Java架构师六大互联网公司面试经历总结

Java架构师面试经历 Java架构师面试经历从58同城——华为 ——招商银行网络中心——金蝶互联网公司GR——苏宁易购 ——蚂蚁金服,看完鬼知道我经历了什么,但是每一次都是成长。本人从2013年...

java知识分子
04/09
42
0
阿里面试回来,想和Java程序员谈一谈

引言 其实本来真的没打算写这篇文章,主要是LZ得记忆力不是很好,不像一些记忆力强的人,面试完以后,几乎能把自己和面试官的对话都给记下来。LZ自己当初面试完以后,除了记住一些聊过的知识...

Lunaqi
2018/01/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

spring cloud

一、从面试题入手 1.1、什么事微服务 1.2、微服务之间如何独立通讯的 1.3、springCloud和Dubbo有哪些区别 1.通信机制:DUbbo基于RPC远程过程调用;微服务cloud基于http restFUL API 1.4、spr...

榴莲黑芝麻糊
4分钟前
0
0
Executor线程池原理与源码解读

线程池为线程生命周期的开销和资源不足问题提供了解决方 案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。 线程实现方式 Thread、Runnable、Callable //实现Runnable接口的...

小强的进阶之路
昨天
6
0
maven 环境隔离

解决问题 即 在 resource 文件夹下面 ,新增对应的资源配置文件夹,对应 开发,测试,生产的不同的配置内容 <resources> <resource> <directory>src/main/resources.${deplo......

之渊
昨天
8
0
详解箭头函数和普通函数的区别以及箭头函数的注意事项、不适用场景

箭头函数是ES6的API,相信很多人都知道,因为其语法上相对于普通函数更简洁,深受大家的喜爱。就是这种我们日常开发中一直在使用的API,大部分同学却对它的了解程度还是不够深... 普通函数和...

OBKoro1
昨天
7
0
轻量级 HTTP(s) 代理 TinyProxy

CentOS 下安装 TinyProxy yum install -y tinyproxy 启动、停止、重启 # 启动service tinyproxy start# 停止service tinyproxy stop# 重启service tinyproxy restart 相关配置 默认...

Anoyi
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部