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

场景:

??昨天有位朋友去面试,我问他面试问了哪些问题,其中问了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");
    }
}

原文地址:https://www.cnblogs.com/hujinshui/p/11350435.html

时间: 2024-10-11 11:35:31

Integer面试连环炮以及源码分析的相关文章

Integer和Long部分源码分析

Integer和Long的java中使用特别广泛,本人主要一下Integer.toString(int i)和Long.toString(long i)方法,其他方法都比较容易理解. Integer.toString(int i)和Long.toString(long i),以Integer.toString(int i)为例,先看源码: 1 /** 2 * Returns a {@code String} object representing the 3 * specified intege

面试必会之HashMap源码分析

相关文章 面试必会之ArrayList源码分析 面试必会之LinkedList源码分析 简介 HashMap最早出现在JDK1.2中,底层基于散列算法实现.HashMap 允许 null 键和 null 值,是非线程安全类,在多线程环境下可能会存在问题. 1.8版本的HashMap数据结构: 为什么有的是链表有的是红黑树? 默认链表长度大于8时转为树 结构 Node是HhaspMap中的一个静态内部类 : 1 //Node是单向链表,实现了Map.Entry接口 2 static class N

JDK源码分析-Integer

Integer是平时开发中最常用的类之一,但是如果没有研究过源码很多特性和坑可能就不知道,下面深入源码来分析一下Integer的设计和实现. Integer: 继承结构: -java.lang.Object --java.lang.Number ---java.lang.Integer 其中父类Number是个抽象类,是所有数字类型相关的类的父类,例如Double.Float.Integer.Long 和 Short. Integer类还实现了Comparable接口用以比较两个Integer的

Java面试准备之String类专项突破+源码分析

String的源码中有很多Arrays的方法使用,建议先参阅Arrays的类库 基本介绍: String是一个比较特殊的类,有很多种建立的方法. 如果使用传统的构造方法比如 String s = new String("字符串");这时的对象会在堆上分配,这时候比较两个字符串地址就不相等,而用""双引号包起来的内容会在常量池中做停留,这时如果有两个内容一样的地址就一样了. 因此,使用==来比较字符串是不靠谱的. String类还实现了三个接口:Serializabl

Java BAT大型公司面试必考技能视频-1.HashMap源码分析与实现

视频通过以下四个方面介绍了HASHMAP的内容 一. 什么是HashMap Hash散列将一个任意的长度通过某种算法(Hash函数算法)转换成一个固定的值. MAP:地图 x,y 存储 总结:通过HASH出来的值,然后通过值定位到这个MAP,然后value存储到这个MAP中的HASHMAP基本原理 1. KEY 是否可以为空?可以,Null当成一个Key来存储 2. 如果Hash KEY重复了会覆盖吗?会覆盖,但返回旧的值 3. HASHMAP什么时候做扩容?put 的时候,阀值高于或等于0.7

面试(1)-HashMap原理与源码分析(JDK1.8)

1.HashMap介绍 HashMap为Map接口的一个实现类,实现了Map所有的操作.HashMap除了允许key.value为null值和非线程安全外,其他实现几乎和HashTable一致.HashMap使用散列存储的方式保存kay-value键值对,因此其不支持数据保存的顺序.如果想要使用有序容器可以使用LinkedHashMap.在性能上当HashMap中保存的key的哈希算法能够均匀的分布在每个bucket中的时候,HashMap在基本的get和set操作的的时间复杂度都是O(n).在

Handler、Looper、MessageQueue、Thread源码分析

关于这几个之间的关系以及源码分析的文章应该挺多的了,不过既然学习了,还是觉得整理下,印象更深刻点,嗯,如果有错误的地方欢迎反馈. 转载请注明出处:http://www.cnblogs.com/John-Chen/p/4396268.html 对应关系:   1.Handler 不带Looper的构造器 /** * Use the {@link Looper} for the current thread with the specified callback interface * and se

Android异步消息处理机制详解及源码分析

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处,尊重分享成果] 最近相对来说比较闲,加上养病,所以没事干就撸些自己之前的知识点为博客,方便自己也方便别人. 1 背景 之所以选择这个知识点来分析有以下几个原因: 逛GitHub时发现关注的isuss中有人不停的在讨论Android中的Looper , Handler , Me

Android应用AsyncTask处理机制详解及源码分析

[工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处,尊重分享成果] 1 背景 Android异步处理机制一直都是Android的一个核心,也是应用工程师面试的一个知识点.前面我们分析了Handler异步机制原理(不了解的可以阅读我的<Android异步消息处理机制详解及源码分析>文章),这里继续分析Android的另一个异步机制AsyncTask的原理. 当使用线程和Handler组合实现异步处理时,当每次执行耗时操作都创建一条新线程进行处理,性能开销会比