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.getSavedProperty和System.getProperty有啥区别?
答:唯一的区别是,System.getProperty只能获取非内部的配置信息;例如java.lang.Integer.IntegerCache.high、sun.zip.disableMemoryMapping、sun.java.launcher.diag、sun.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");
}
}
Integer面试连环炮以及源码分析的更多相关文章
- Integer面试连环炮以及源码分析(转)
场景: 昨天有位朋友去面试,我问他面试问了哪些问题,其中问了Integer相关的问题,以下就是面试官问的问题,还有一些是我对此做了扩展. 问:两个new Integer 128相等吗? 答:不.因 ...
- Integer和Long部分源码分析
Integer和Long的java中使用特别广泛,本人主要一下Integer.toString(int i)和Long.toString(long i)方法,其他方法都比较容易理解. Integer. ...
- 面试必会之HashMap源码分析
相关文章 面试必会之ArrayList源码分析 面试必会之LinkedList源码分析 简介 HashMap最早出现在JDK1.2中,底层基于散列算法实现.HashMap 允许 null 键和 nul ...
- 面试必会之ArrayList源码分析&手写ArrayList
简介 ArrayList是我们开发中非常常用的数据存储容器之一,其底层是数组实现的,我们可以在集合中存储任意类型的数据,ArrayList是线程不安全的,非常适合用于对元素进行查找,效率非常高. 线程 ...
- ThreadPoolExecutor源码分析-面试问烂了的Java线程池执行流程,如果要问你具体的执行细节,你还会吗?
Java版本:8u261. 对于Java中的线程池,面试问的最多的就是线程池中各个参数的含义,又或者是线程池执行的流程,彷佛这已成为了固定的模式与套路.但是假如我是面试官,现在我想问一些更细致的问题, ...
- JDK源码分析-Integer
Integer是平时开发中最常用的类之一,但是如果没有研究过源码很多特性和坑可能就不知道,下面深入源码来分析一下Integer的设计和实现. Integer: 继承结构: -java.lang.Obj ...
- Java BAT大型公司面试必考技能视频-1.HashMap源码分析与实现
视频通过以下四个方面介绍了HASHMAP的内容 一. 什么是HashMap Hash散列将一个任意的长度通过某种算法(Hash函数算法)转换成一个固定的值. MAP:地图 x,y 存储 总结:通过HA ...
- 设计模式(十二)——享元模式(Integer缓冲池源码分析)
1 展示网站项目需求 小型的外包项目,给客户 A 做一个产品展示网站,客户 A 的朋友感觉效果不错,也希望做这样的产品展示网站,但是要求都有些不同: 1) 有客户要求以新闻的形式发布 2) 有客户人要 ...
- 面试官:来谈谈限流-RateLimiter源码分析
RateLimiter有两个实现类:SmoothBursty和SmoothWarmingUp,其都是令牌桶算法的变种实现,区别在于SmoothBursty加令牌的速度是恒定的,而SmoothWarmi ...
随机推荐
- Eclipse 单个tomcat多个项目部署原理(tomcat配置的环境变量catalina.home和catalina.base)
一:概念 catalina.home(安装目录):指向公用信息的位置,就是bin和lib的父目录. catalina.base(工作目录):指向每个Tomcat目录私有信息的位置,就是conf.log ...
- 静默安装weblogic12c提示INST-07319: Oracle 主目录(O) 位置的验证失败。指定的位置已存在, 是非空目录并且不是有效的 Oracle 主目录
[xxx@localhost bea12c3]$ java -jar fmw_12.2.1.3.0_wls.jar -silent -responseFile /app/bea12c3/weblogi ...
- Java对象在内存的结构
一.内存布局 对象在内存中存储的结构由三部分组成:对象头.实例数据.对齐填充. 对象头 MarkWord(标记字段):哈希码.分代年龄.锁标志位.偏向线程ID.偏向时间戳等信息.Mark Word被设 ...
- PHP设计模式 - 状态模式
状态模式当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类.状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况.把状态的判断逻辑转移到表示不同状态的一系列类中,可以 ...
- C/C++ 快速排序实现
#include<iostream> using namespace std; void qS(int *array,int left,int right){ if(left<rig ...
- Unary模式下客户端从开始连接到发送接收数据的主要流程
(原创)C/C/1.25.0-dev grpc-c/8.0.0, 使用的例子是自带的例子GreeterClient grpc Unary模式下客户端从开始连接到发送数据的主要流程 graph TD; ...
- redis 设置自启动
redis 设置自启动 1.创建服务(redis.conf 配置文件要注意,经过cp产生了很多个redis.conf) vim /lib/systemd/system/redis.service [U ...
- datanode启动异常(Incompatible clusterIDs)
问题: 正常start-all.sh无法启动datanode进程,但是./hadoop-daemon.sh start datanode又可以启动.过一会后datanode进程又莫名消失. 原理: 多 ...
- 6. 运行Spark SQL CLI
Spark SQL CLI可以很方便的在本地运行Hive元数据服务以及从命令行执行任务查询.需要注意的是,Spark SQL CLI不能与Thrift JDBC服务交互.在Spark目录下执行如下命令 ...
- pytest_assert断言
前言 断言是写自动化测试基本最重要的一步,一个用例没有断言,就失去了自动化测试的意义了.什么是断言呢? 简单来讲就是实际结果和期望结果去对比,符合预期那就测试pass,不符合预期那就测试 failed ...