apacheapollo apollo启动之后报空指针异常是什么原因

&figure&&img src=&https://pic3.zhimg.com/v2-d4a97d7c07b85b2a85d96f0_b.jpg& data-rawwidth=&580& data-rawheight=&300& class=&origin_image zh-lightbox-thumb& width=&580& data-original=&https://pic3.zhimg.com/v2-d4a97d7c07b85b2a85d96f0_r.jpg&&&/figure&&p&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-804effbaf311a84a917d3ee1f7528145_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&391& data-rawheight=&220& class=&content_image& width=&391&&&/figure&&p&&br&今天逛了逛Github,顺手精选出了一下近几个月以来Github上最热门的12个Java项目。如果遇到自己感兴趣的开源项目,不妨去学习一下哦!&/p&&h2&1. java-design-patterns(Star:36k)&/h2&&h2&Github地址:&/h2&&p&&a href=&http://link.zhihu.com/?target=https%3A//github.com/iluwatar/java-design-patterns& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/iluwatar/jav&/span&&span class=&invisible&&a-design-patterns&/span&&span class=&ellipsis&&&/span&&/a&&/p&&h2&介绍:&/h2&&p&设计模式是形式化的最佳实践,程序员可以在设计应用程序或系统时使用它来解决常见问题。&/p&&p&设计模式可以通过提供经过验证的经过验证的开发范例来加速开发过程。&/p&&p&重用设计模式有助于防止可能导致重大问题的细微问题,并且还可以提高熟悉模式的编码人员和架构师的代码可读性。&/p&&h2&2. Elasticsearch(Star:32k)&/h2&&h2&Github地址:&/h2&&p&&a href=&http://link.zhihu.com/?target=https%3A//github.com/elastic/elasticsearch& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/elastic/elas&/span&&span class=&invisible&&ticsearch&/span&&span class=&ellipsis&&&/span&&/a&&/p&&h2&介绍:&/h2&&p&ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。&/p&&p&我们建立一个网站或应用程序,并要添加搜索功能,但是想要完成搜索工作的创建是非常困难的。我们希望搜索解决方案要运行速度快,我们希望能有一个零配置和一个完全免费的搜索模式,我们希望能够简单地使用JSON通过HTTP来索引数据,我们希望我们的搜索服务器始终可用,我们希望能够从一台开始并扩展到数百台,我们要实时搜索,我们要简单的多租户,我们希望建立一个云的解决方案。因此我们利用Elasticsearch来解决所有这些问题及可能出现的更多其它问题。&/p&&h2&3. Interview-Notebook(Start:28k)&/h2&&h2&Github地址:&/h2&&p&&a href=&http://link.zhihu.com/?target=https%3A//github.com/CyC2018/Interview-Notebook& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/CyC2018/Inte&/span&&span class=&invisible&&rview-Notebook&/span&&span class=&ellipsis&&&/span&&/a&&/p&&h2&介绍:&/h2&&p&这个仓库是作者的一个学习笔记,主要总结一些比较重要的知识点。&/p&&h2&4. okhttp(Start:27k)&/h2&&h2&Github地址:&/h2&&p&&a href=&http://link.zhihu.com/?target=https%3A//github.com/square/okhttp& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/square/okhtt&/span&&span class=&invisible&&p&/span&&span class=&ellipsis&&&/span&&/a&&/p&&h2&介绍:&/h2&&p&适用于Android和Java应用程序的HTTP + HTTP / 2客户端。&/p&&h2&5. spring-boot(Star:26k)&/h2&&h2&Github地址:&/h2&&p&&a href=&http://link.zhihu.com/?target=https%3A//github.com/spring-projects/spring-boot& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/spring-proje&/span&&span class=&invisible&&cts/spring-boot&/span&&span class=&ellipsis&&&/span&&/a&&/p&&h2&介绍:&/h2&&p&虽然Spring的组件代码是轻量级的,但它的配置却是重量级的(需要大量XML配置),不过Spring Boot 让这一切成为了过去。&/p&&p&关于Spring Boot官方的介绍:&/p&&blockquote&Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”…Most Spring Boot applications need very little Spring configuration.(Spring Boot可以轻松创建独立的生产级基于Spring的应用程序,只要通过 “just run”(可能是run ‘Application’或java -jar 或 tomcat 或 maven插件run 或 shell脚本)便可以运行项目。大部分Spring Boot项目只需要少量的配置即可)&/blockquote&&h2&6. guava(Star:25k)&/h2&&h2&Github地址:&/h2&&p&&a href=&http://link.zhihu.com/?target=https%3A//github.com/google/guava& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/google/guava&/span&&span class=&invisible&&&/span&&/a&&/p&&h2&介绍:&/h2&&p&Guava是一组核心库,包括新的集合类型(例如multimap和multiset),不可变集合,图形库,函数类型,内存缓存以及用于并发,I / O,散列,API /实用程序 ,反射,字符串处理等等!&/p&&h2&7. incubator-dubbo(Star:20k)&/h2&&h2&Github地址:&/h2&&p&&a href=&http://link.zhihu.com/?target=https%3A//github.com/apache/incubator-dubbo& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/apache/incub&/span&&span class=&invisible&&ator-dubbo&/span&&span class=&ellipsis&&&/span&&/a&&/p&&h2&介绍:&/h2&&p&Apache Dubbo(孵化)是阿里开源的一个基于Java的高性能开源RPC框架。&/p&&h2&8. proxyee-down(Star:11k)&/h2&&h2&Github地址:&/h2&&p&&a href=&http://link.zhihu.com/?target=https%3A//github.com/proxyee-down-org/proxyee-down& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/proxyee-down&/span&&span class=&invisible&&-org/proxyee-down&/span&&span class=&ellipsis&&&/span&&/a&&/p&&h2&介绍:&/h2&&p&http下载工具,基于http代理,支持多连接分块下载&/p&&h2&9. weixin-java-tools(Star:8.4k)&/h2&&h2&Github地址&/h2&&p&&a href=&http://link.zhihu.com/?target=https%3A//github.com/Wechat-Group/weixin-java-tools& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/Wechat-Group&/span&&span class=&invisible&&/weixin-java-tools&/span&&span class=&ellipsis&&&/span&&/a&&/p&&h2&介绍&/h2&&p&可能是目前最好最全的微信Java开发工具包,支持包括微信支付、开放平台、小程序、企业号和公众号等的开发&/p&&h2&10. Java-Interview(Star:7k)&/h2&&p&多数是一些 Java 基础知识、底层原理、算法详解。也有上层应用设计,其中不乏一些大厂面试真题。&/p&&h2&Github地址:&/h2&&p&&a href=&http://link.zhihu.com/?target=https%3A//github.com/crossoverJie/Java-Interview& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/crossoverJie&/span&&span class=&invisible&&/Java-Interview&/span&&span class=&ellipsis&&&/span&&/a&&/p&&h2&介绍:&/h2&&p&多数是一些 Java 基础知识、底层原理、算法详解。也有上层应用设计,其中不乏一些大厂面试真题。&/p&&h2&11. apollo(Star:6.5k)&/h2&&h2&Github地址&/h2&&p&&a href=&http://link.zhihu.com/?target=https%3A//github.com/ctripcorp/apollo& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/ctripcorp/ap&/span&&span class=&invisible&&ollo&/span&&span class=&ellipsis&&&/span&&/a&&/p&&h2&介绍&/h2&&p&Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。&/p&&h2&12. jib(Star:3.4k)&/h2&&h2&Github地址:&/h2&&p&&a href=&http://link.zhihu.com/?target=https%3A//github.com/GoogleContainerTools/jib& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/GoogleContai&/span&&span class=&invisible&&nerTools/jib&/span&&span class=&ellipsis&&&/span&&/a&&/p&&h2&介绍:&/h2&&p&Google 最近开源一款新的 Java 工具 Jib ,旨在让开发者使用他们熟悉的工具更轻松地将 Java 应用程序容器化。&/p&&p&容器使 Java 开发者比以往任何时候都更靠近“一次编写,随处运行” 的工作流程,但容器化 Java 应用却并非易事:你必须先编写 Dockerfile ,root 后运行 Docker 守护进程,等待构建完成,最后将镜像推送至远程注册表。Jib 将处理将应用打包到容器镜像过程中的所有步骤,它直接与 Maven 和 Gradle Java 开发环境集成,不需要你编写 Dockerfile 或安装 Docker ,只需将其作为插件添加到你的构建中,就可以立即将 Java 应用容器化。&/p&&p&相关阅读:《Google 正式开源 Jib ,帮助 Java 应用快速容器化》:&a href=&http://link.zhihu.com/?target=https%3A//www.oschina.net/news/97892/google-opensource-jib& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&oschina.net/news/97892/&/span&&span class=&invisible&&google-opensource-jib&/span&&span class=&ellipsis&&&/span&&/a&&/p&&h2&未来可能会上热门TOP的项目&/h2&&h2&13. Java-Guide(Star:650star)&/h2&&h2&Github地址:&/h2&&p&&a href=&http://link.zhihu.com/?target=https%3A//github.com/Snailclimb/Java-Guide& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/Snailclimb/J&/span&&span class=&invisible&&ava-Guide&/span&&span class=&ellipsis&&&/span&&/a&&/p&&h2&介绍:&/h2&&p&哈哈 ,皮一下很开心。这是我自己开源的一份文档,目前仍在完善中,欢迎各位英雄好汉一起完善。&/p&&p&该文档主要是笔主在学习Java的过程中的一些学习笔记,但是为了能够设计到大部分后端面试所需的技术知识点我也会引用别人的优秀文章。 该文档设计的主要内容包括: Java、 数据结构与算法、计算机网络与数据通信、 操作系统、主流框架、数据存储、架构、面试必备知识点等等。相信不论你是前端还是后端都能在这份文档中收获到东西。&/p&&blockquote&如果想要获取更多我的原创文章,欢迎关注我的微信公众号:&&b&Java面试通关手册&/b&& 。无套路,希望能与您共同进步,互相学习。&/blockquote&&p&&/p&&p&&/p&
今天逛了逛Github,顺手精选出了一下近几个月以来Github上最热门的12个Java项目。如果遇到自己感兴趣的开源项目,不妨去学习一下哦!1. java-design-patterns(Star:36k)Github地址:介绍:设计模式是形式化的最佳实践,程序员可以在…
&figure&&img src=&https://pic4.zhimg.com/v2-a_b.jpg& data-rawwidth=&900& data-rawheight=&500& class=&origin_image zh-lightbox-thumb& width=&900& data-original=&https://pic4.zhimg.com/v2-a_r.jpg&&&/figure&&h2&前言&/h2&&blockquote&只有光头才能变强&/blockquote&&p&JVM在准备面试的时候就有看了,一直没时间写笔记。现在到了一家公司实习,闲的时候就写写,刷刷JVM博客,刷刷电子书。&/p&&p&学习JVM的目的也很简单:&/p&&ul&&li&能够知道JVM是什么,为我们干了什么,具体是怎么干的。能够理解到一些初学时不懂的东西&/li&&li&在面试的时候有谈资&/li&&li&能装逼&/li&&/ul&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-0e9cb59842b74fea5d3301d29eff8ee7_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&2818& data-rawheight=&4096& class=&origin_image zh-lightbox-thumb& width=&2818& data-original=&https://pic4.zhimg.com/v2-0e9cb59842b74fea5d3301d29eff8ee7_r.jpg&&&/figure&&p&&br&&/p&&p&(图片来源:&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&&span class=&invisible&&https://&/span&&span class=&visible&&zhuanlan.zhihu.com/p/25&/span&&span class=&invisible&&511795&/span&&span class=&ellipsis&&&/span&&/a&,侵删)&/p&&blockquote&声明:全文默认指的是HotSpot VM&/blockquote&&h2&一、简单聊聊JVM&/h2&&h2&1.1先来看看简单的Java程序&/h2&&p&现在我有一个JavaBean:&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&&span class=&kd&&public&/span& &span class=&kd&&class&/span& &span class=&nc&&Java3y&/span& &span class=&o&&{&/span&
&span class=&c1&&// 姓名
&span class=&kd&&private&/span& &span class=&n&&String&/span& &span class=&n&&name&/span&&span class=&o&&;&/span&
&span class=&c1&&// 年龄
&span class=&kd&&private&/span& &span class=&kt&&int&/span& &span class=&n&&age&/span&&span class=&o&&;&/span&
&span class=&c1&&//.....各种get/set方法/toString&/span&
&span class=&o&&}&/span&
&/code&&/pre&&/div&&p&一个测试类:&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&&span class=&kd&&public&/span& &span class=&kd&&class&/span& &span class=&nc&&Java3yTest&/span& &span class=&o&&{&/span&
&span class=&kd&&public&/span& &span class=&kd&&static&/span& &span class=&kt&&void&/span& &span class=&nf&&main&/span&&span class=&o&&(&/span&&span class=&n&&String&/span&&span class=&o&&[]&/span& &span class=&n&&args&/span&&span class=&o&&)&/span& &span class=&o&&{&/span&
&span class=&n&&Java3y&/span& &span class=&n&&java3y&/span& &span class=&o&&=&/span& &span class=&k&&new&/span& &span class=&n&&Java3y&/span&&span class=&o&&();&/span&
&span class=&n&&java3y&/span&&span class=&o&&.&/span&&span class=&na&&setName&/span&&span class=&o&&(&/span&&span class=&s&&&Java3y&&/span&&span class=&o&&);&/span&
&span class=&n&&System&/span&&span class=&o&&.&/span&&span class=&na&&out&/span&&span class=&o&&.&/span&&span class=&na&&println&/span&&span class=&o&&(&/span&&span class=&n&&java3y&/span&&span class=&o&&);&/span&
&span class=&o&&}&/span&
&span class=&o&&}&/span&
&/code&&/pre&&/div&&p&我们在初学的时候肯定用过&code&javac&/code&来编译&code&.java&/code&文件代码,用过&code&java&/code&命令来执行编译后生成的&code&.class&/code&文件。&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-a58fe5edf4f8c_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1000& data-rawheight=&73& class=&origin_image zh-lightbox-thumb& width=&1000& data-original=&https://pic2.zhimg.com/v2-a58fe5edf4f8c_r.jpg&&&/figure&&p&&br&&/p&&p&Java源文件:&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-ddee6ceeb8e_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1208& data-rawheight=&250& class=&origin_image zh-lightbox-thumb& width=&1208& data-original=&https://pic3.zhimg.com/v2-ddee6ceeb8e_r.jpg&&&/figure&&p&&br&&/p&&p&在使用IDE点击运行的时候其实就是将这两个命令&b&结合&/b&起来了(编译并运行),方便我们开发。&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-9e9dce9f887_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&718& data-rawheight=&556& class=&origin_image zh-lightbox-thumb& width=&718& data-original=&https://pic4.zhimg.com/v2-9e9dce9f887_r.jpg&&&/figure&&p&&br&&/p&&p&生成class文件&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-41b5d76e4cab4dbd1652aef4f84a03cb_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1202& data-rawheight=&290& class=&origin_image zh-lightbox-thumb& width=&1202& data-original=&https://pic4.zhimg.com/v2-41b5d76e4cab4dbd1652aef4f84a03cb_r.jpg&&&/figure&&p&&br&&/p&&p&解析class文件得到结果&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-bc3dbc9c8f0cbf349bf8d_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&980& data-rawheight=&173& class=&origin_image zh-lightbox-thumb& width=&980& data-original=&https://pic2.zhimg.com/v2-bc3dbc9c8f0cbf349bf8d_r.jpg&&&/figure&&p&&br&&/p&&h2&1.2编译过程&/h2&&p&&code&.java&/code&文件是由Java源码编译器(上述所说的&b&javac.exe&/b&)来完成,流程图如下所示:&/p&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-25bad8d9ae462dc46d9024_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&720& data-rawheight=&203& class=&origin_image zh-lightbox-thumb& width=&720& data-original=&https://pic1.zhimg.com/v2-25bad8d9ae462dc46d9024_r.jpg&&&/figure&&p&&br&&/p&&p&Java源码编译由以下&b&三个&/b&过程组成:&/p&&ul&&li&分析和输入到符号表&/li&&li&注解处理&/li&&li&语义分析和生成class文件&/li&&/ul&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-89f2ef3d02cf0b25e43bd52_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1482& data-rawheight=&210& class=&origin_image zh-lightbox-thumb& width=&1482& data-original=&https://pic3.zhimg.com/v2-89f2ef3d02cf0b25e43bd52_r.jpg&&&/figure&&p&&br&&/p&&h2&1.2.1编译时期-语法糖&/h2&&blockquote&语法糖可以看做是&b&编译器实现的一些“小把戏”&/b&,这些“小把戏”可能会使得&b&效率“大提升”。&/b&&/blockquote&&p&最值得说明的就是&b&泛型&/b&了,这个语法糖可以说我们是经常会使用到的!&/p&&ul&&li&泛型只会在Java源码中存在,&b&编译过后&/b&会被替换为原来的原生类型(Raw Type,也称为裸类型)了。这个过程也被称为:&b&泛型擦除&/b&。&/li&&/ul&&p&有了泛型这颗语法糖以后:&/p&&ul&&li&代码更加简洁【不用强制转换】&/li&&li&程序更加健壮【只要编译时期没有警告,那么运行时期就不会出现ClassCastException异常】&/li&&li&可读性和稳定性【在编写集合的时候,就限定了类型】&/li&&/ul&&p&了解泛型更多的知识:&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=https%3A//segmentfault.com/a/0746& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&segmentfault.com/a/1190&/span&&span class=&invisible&&&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&1.3JVM实现跨平台&/h2&&p&至此,我们通过&code&javac.exe&/code&编译器编译我们的&code&.java&/code&源代码文件生成出&code&.class&/code&文件了!&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-1b23fe0e9fd3c6997293_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&986& data-rawheight=&247& class=&origin_image zh-lightbox-thumb& width=&986& data-original=&https://pic4.zhimg.com/v2-1b23fe0e9fd3c6997293_r.jpg&&&/figure&&p&&br&&/p&&p&这些&code&.class&/code&文件很明显是&b&不能直接运行&/b&的,它不像C语言(编译cpp后生成exe文件直接运行)&/p&&p&这些&code&.class&/code&文件是交&b&由JVM来解析运行&/b&!&/p&&ul&&li&JVM是运行在操作系统之上的,每个操作系统的指令是不同的,而&b&JDK是区分操作系统的&/b&,只要你的本地系统装了JDK,这个JDK就是能够和当前系统兼容的。&/li&&li&而class字节码运行在JVM之上,所以&b&不用关心class字节码是在哪个操作系统编译的&/b&,只要符合JVM规范,那么,这个字节码文件就是可运行的。&/li&&li&所以Java就做到了跨平台---&一次编译,到处运行!&/li&&/ul&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-de21e8e8bce8a_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1057& data-rawheight=&488& class=&origin_image zh-lightbox-thumb& width=&1057& data-original=&https://pic3.zhimg.com/v2-de21e8e8bce8a_r.jpg&&&/figure&&p&&br&&/p&&h2&1.4class文件和JVM的恩怨情仇&/h2&&h2&1.4.1类的加载时机&/h2&&p&现在我们例子中生成的两个&code&.class&/code&文件&b&都会直接被加载到JVM中吗&/b&??&/p&&p&虚拟机规范则是严格规定了有且只有5种情况必须&b&立即对类进行“初始化”&/b&(class文件加载到JVM中):&/p&&ul&&li&创建类的实例(new 的方式)。访问某个类或接口的静态变量,或者对该静态变量赋值,调用类的静态方法&/li&&li&反射的方式&/li&&li&初始化某个类的子类,则其父类也会被初始化&/li&&li&Java虚拟机启动时被标明为启动类的类,直接使用java.exe命令来运行某个主类(包含main方法的那个类)&/li&&li&当使用JDK1.7的动态语言支持时(....)&/li&&/ul&&p&所以说:&/p&&ul&&li&Java类的加载是动态的,它并不会一次性将所有类全部加载后再运行,而是保证程序运行的基础类(像是基类)完全加载到jvm中,至于其他类,&b&则在需要的时候才加载&/b&。这当然就是为了&b&节省内存开销&/b&。&/li&&/ul&&h2&1.4.2如何将类加载到jvm&/h2&&p&class文件是通过&b&类的加载器&/b&装载到jvm中的!&/p&&p&Java&b&默认有三种类加载器&/b&:&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-a53cfcddba7e1_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&386& data-rawheight=&384& class=&content_image& width=&386&&&/figure&&p&&br&&/p&&p&各个加载器的工作责任:&/p&&ul&&li&1)Bootstrap ClassLoader:负责加载$JAVA_HOME中jre/lib/&b&rt.jar&/b&里所有的class,由C++实现,不是ClassLoader子类&/li&&li&2)Extension ClassLoader:负责加载java平台中&b&扩展功能&/b&的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包&/li&&li&3)App ClassLoader:负责记载&b&classpath&/b&中指定的jar包及目录中class&/li&&/ul&&p&工作过程:&/p&&ul&&li&1、当AppClassLoader加载一个class时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成。&/li&&li&2、当ExtClassLoader加载一个class时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader去完成。&/li&&li&3、如果BootStrapClassLoader加载失败(例如在$JAVA_HOME/jre/lib里未查找到该class),会使用ExtClassLoader来尝试加载;&/li&&li&4、若ExtClassLoader也加载失败,则会使用AppClassLoader来加载&/li&&li&5、如果AppClassLoader也加载失败,则会报出异常ClassNotFoundException&/li&&/ul&&p&其实这就是所谓的&b&双亲委派模型&/b&。简单来说:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把&b&请求委托给父加载器去完成,依次向上&/b&。&/p&&p&好处:&/p&&ul&&li&&b&防止内存中出现多份同样的字节码&/b&(安全性角度)&/li&&/ul&&p&特别说明:&/p&&ul&&li&类加载器在成功加载某个类之后,会把得到的 &code&java.lang.Class&/code&类的实例缓存起来。下次再请求加载该类的时候,类加载器会直接使用缓存的类的实例,而&b&不会尝试再次加载&/b&。&/li&&/ul&&h2&1.4.2类加载详细过程&/h2&&p&加载器加载到jvm中,接下来其实又分了&b&好几个步骤&/b&:&/p&&ul&&li&加载,查找并加载类的二进制数据,在Java堆中也&b&创建一个java.lang.Class类的对象&/b&。&/li&&li&连接,连接又包含三块内容:验证、准备、初始化。
- 1)验证,文件格式、元数据、字节码、符号引用验证;
- 2)准备,为类的静态变量分配内存,并将其初始化为默认值;
- 3)解析,把类中的符号引用转换为直接引用&/li&&li&初始化,为类的静态变量赋予正确的初始值。&/li&&/ul&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-8e29a3d10efa9ff06fb02c_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&694& data-rawheight=&225& class=&origin_image zh-lightbox-thumb& width=&694& data-original=&https://pic1.zhimg.com/v2-8e29a3d10efa9ff06fb02c_r.jpg&&&/figure&&p&&br&&/p&&h2&1.4.3JIT即时编辑器&/h2&&p&一般我们可能会想:JVM在加载了这些class文件以后,针对这些字节码,&b&逐条取出,逐条执行&/b&--&解析器解析。&/p&&p&但如果是这样的话,那就&b&太慢&/b&了!&/p&&p&我们的JVM是这样实现的:&/p&&ul&&li&就是把这些Java字节码&b&重新编译优化&/b&,生成机器码,让CPU直接执行。这样编出来的代码效率会更高。&/li&&li&编译也是要花费时间的,我们一般对&b&热点代码&/b&做编译,&b&非热点代码直接解析&/b&就好了。&/li&&/ul&&blockquote&热点代码解释:一、多次调用的方法。二、多次执行的循环体&/blockquote&&p&使用热点探测来&b&检测是否为热点代码&/b&,热点探测有两种方式:&/p&&ul&&li&采样&/li&&li&计数器&/li&&/ul&&p&目前HotSpot使用的是&b&计数器的方式&/b&,它为每个方法准备了两类计数器:&/p&&ul&&li&方法调用计数器(Invocation
Counter)&/li&&li&回边计数器(Back
EdgeCounter)。&/li&&li&在确定虚拟机运行参数的前提下,这两个计数器都有一个确定的阈值,&b&当计数器超过阈值溢出了,就会触发JIT编译&/b&。&/li&&/ul&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-bbb574b7dd7c_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1389& data-rawheight=&967& class=&origin_image zh-lightbox-thumb& width=&1389& data-original=&https://pic1.zhimg.com/v2-bbb574b7dd7c_r.jpg&&&/figure&&p&&br&&/p&&h2&1.4.4回到例子中&/h2&&p&按我们程序来走,我们的&code&Java3yTest.class&/code&文件会被AppClassLoader加载器(因为ExtClassLoader和BootStrap加载器都不会加载它[双亲委派模型])加载到JVM中。&/p&&p&随后发现了要使用Java3y这个类,我们的&code&Java3y.class&/code&文件会被AppClassLoader加载器(因为ExtClassLoader和BootStrap加载器都不会加载它[双亲委派模型])加载到JVM中&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-19bef316be_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&961& data-rawheight=&433& class=&origin_image zh-lightbox-thumb& width=&961& data-original=&https://pic3.zhimg.com/v2-19bef316be_r.jpg&&&/figure&&p&&br&&/p&&p&详情参考:&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=https%3A//www.mrsssswan.club//jvm-start1/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&mrsssswan.club/2018/06/&/span&&span class=&invisible&&30/jvm-start1/&/span&&span class=&ellipsis&&&/span&&/a&---浅解JVM加载class文件&/li&&li&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&&span class=&invisible&&https://&/span&&span class=&visible&&zhuanlan.zhihu.com/p/28&/span&&span class=&invisible&&476709&/span&&span class=&ellipsis&&&/span&&/a&---JVM杂谈之JIT&/li&&/ul&&p&扩展阅读:&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=https%3A//www.ibm.com/developerworks/cn/java/j-lo-classloader/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&ibm.com/developerworks/&/span&&span class=&invisible&&cn/java/j-lo-classloader/&/span&&span class=&ellipsis&&&/span&&/a&---深入探讨 Java 类加载器&/li&&li&&a href=&http://link.zhihu.com/?target=https%3A//www.ibm.com/developerworks/cn/java/j-lo-just-in-time/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&ibm.com/developerworks/&/span&&span class=&invisible&&cn/java/j-lo-just-in-time/&/span&&span class=&ellipsis&&&/span&&/a&---深入浅出 JIT 编译器&/li&&li&&a href=&https://www.zhihu.com/question/& class=&internal&&&span class=&invisible&&https://www.&/span&&span class=&visible&&zhihu.com/question/4671&/span&&span class=&invisible&&9811&/span&&span class=&ellipsis&&&/span&&/a&---Java 类加载器(ClassLoader)的实际使用场景有哪些?&/li&&/ul&&h2&1.5类加载完以后JVM干了什么?&/h2&&p&在类加载检查通过后,接下来虚拟机&b&将为新生对象分配内存&/b&。&/p&&h2&1.5.1JVM的内存模型&/h2&&p&首先我们来了解一下JVM的内存模型的怎么样的:&/p&&ul&&li&基于jdk1.8画的JVM的内存模型---&我画得比较&b&细&/b&。&/li&&/ul&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-539ff9e77dd6cfcf4bee442c02db5d3a_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1008& data-rawheight=&622& class=&origin_image zh-lightbox-thumb& width=&1008& data-original=&https://pic3.zhimg.com/v2-539ff9e77dd6cfcf4bee442c02db5d3a_r.jpg&&&/figure&&p&&br&&/p&&p&简单看了一下内存模型,简单看看每个区域究竟存储的是什么(干的是什么):&/p&&ul&&li&堆:&b&存放对象实例&/b&,几乎所有的对象实例都在这里分配内存&/li&&li&虚拟机栈:虚拟机栈描述的是&b&Java方法执行的内存模型&/b&:每个方法被执行的时候都会同时创建一个&b&栈帧&/b&(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息&/li&&li&本地方法栈:本地方法栈则是为虚拟机使用到的&b&Native方法服务&/b&。&/li&&li&方法区:存储已&b&被虚拟机加载的类元数据信息&/b&(元空间)&/li&&li&程序计数器:当前线程所执行的字节码的&b&行号指示器&/b&&/li&&/ul&&h2&1.5.2例子中的流程&/h2&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-bfc22c856b2c16117e17ecd66e02d49f_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&720& data-rawheight=&361& class=&origin_image zh-lightbox-thumb& width=&720& data-original=&https://pic4.zhimg.com/v2-bfc22c856b2c16117e17ecd66e02d49f_r.jpg&&&/figure&&p&&br&&/p&&p&我来&b&宏观简述&/b&一下我们的例子中的工作流程:&/p&&ul&&li&1、通过&code&java.exe&/code&运行&code&Java3yTest.class&/code&,随后被加载到JVM中,&b&元空间存储着类的信息&/b&(包括类的名称、方法信息、字段信息..)。&/li&&li&2、然后JVM找到Java3yTest的主函数入口(main),为main函数创建栈帧,开始执行main函数&/li&&li&3、main函数的第一条命令是&code&Java3y java3y = new Java3y();&/code&就是让JVM创建一个Java3y对象,但是这时候方法区中没有Java3y类的信息,所以JVM马上加载Java3y类,把Java3y类的类型信息放到方法区中(元空间)&/li&&li&4、加载完Java3y类之后,Java虚拟机做的第一件事情就是在堆区中为一个新的Java3y实例分配内存, 然后调用构造函数初始化Java3y实例,这个&b&Java3y实例持有着指向方法区的Java3y类的类型信息&/b&(其中包含有方法表,java动态绑定的底层实现)的引用&/li&&li&5、当使用&code&java3y.setName(&Java3y&);&/code&的时候,JVM&b&根据java3y引用找到Java3y对象&/b&,然后根据Java3y对象持有的引用定位到方法区中Java3y类的类型信息的&b&方法表&/b&,获得&code&setName()&/code&函数的字节码的地址&/li&&li&6、为&code&setName()&/code&函数创建栈帧,开始运行&code&setName()&/code&函数&/li&&/ul&&p&从微观上其实还做了很多东西,正如上面所说的&b&类加载过程&/b&(加载--&连接(验证,准备,解析)--&初始化),在类加载完之后jvm&b&为其分配内存&/b&(分配内存中也做了非常多的事)。由于这些步骤并不是一步一步往下走,会有很多的“混沌bootstrap”的过程,所以很难描述清楚。&/p&&ul&&li&扩展阅读(先有Class对象还是先有Object):&a href=&https://www.zhihu.com/question/& class=&internal&&&span class=&invisible&&https://www.&/span&&span class=&visible&&zhihu.com/question/3030&/span&&span class=&invisible&&1819&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&p&参考资料:&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=http%3A//www.cnblogs.com/qiumingcheng/p/5398610.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&cnblogs.com/qiumingchen&/span&&span class=&invisible&&g/p/5398610.html&/span&&span class=&ellipsis&&&/span&&/a&---Java程序编译和运行的过程&/li&&li&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&&span class=&invisible&&https://&/span&&span class=&visible&&zhuanlan.zhihu.com/p/25&/span&&span class=&invisible&&713880&/span&&span class=&ellipsis&&&/span&&/a&---Java JVM 运行机制及基本原理&/li&&/ul&&h2&1.6简单聊聊各种常量池&/h2&&p&在写这篇文章的时候,原本以为我对&code&String s = &aaa&;&/code&类似这些题目已经是不成问题了,直到我遇到了&code&String.intern()&/code&这样的方法与诸如&code&String s1 = new String(&1&) + new String(&2&);&/code&混合一起用的时候&/p&&ul&&li&我发现,我还是太年轻了。&/li&&/ul&&p&首先我是先阅读了美团技术团队的这篇文章:&a href=&http://link.zhihu.com/?target=https%3A//tech.meituan.com/in_depth_understanding_string_intern.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&tech.meituan.com/in_dep&/span&&span class=&invisible&&th_understanding_string_intern.html&/span&&span class=&ellipsis&&&/span&&/a&---深入解析String#intern&/p&&p&嗯,然后就懵逼了。我摘抄一下他的例子:&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&&span class=&kd&&public&/span& &span class=&kd&&static&/span& &span class=&kt&&void&/span& &span class=&nf&&main&/span&&span class=&o&&(&/span&&span class=&n&&String&/span&&span class=&o&&[]&/span& &span class=&n&&args&/span&&span class=&o&&)&/span& &span class=&o&&{&/span&
&span class=&n&&String&/span& &span class=&n&&s&/span& &span class=&o&&=&/span& &span class=&k&&new&/span& &span class=&n&&String&/span&&span class=&o&&(&/span&&span class=&s&&&1&&/span&&span class=&o&&);&/span&
&span class=&n&&s&/span&&span class=&o&&.&/span&&span class=&na&&intern&/span&&span class=&o&&();&/span&
&span class=&n&&String&/span& &span class=&n&&s2&/span& &span class=&o&&=&/span& &span class=&s&&&1&&/span&&span class=&o&&;&/span&
&span class=&n&&System&/span&&span class=&o&&.&/span&&span class=&na&&out&/span&&span class=&o&&.&/span&&span class=&na&&println&/span&&span class=&o&&(&/span&&span class=&n&&s&/span& &span class=&o&&==&/span& &span class=&n&&s2&/span&&span class=&o&&);&/span&
&span class=&n&&String&/span& &span class=&n&&s3&/span& &span class=&o&&=&/span& &span class=&k&&new&/span& &span class=&n&&String&/span&&span class=&o&&(&/span&&span class=&s&&&1&&/span&&span class=&o&&)&/span& &span class=&o&&+&/span& &span class=&k&&new&/span& &span class=&n&&String&/span&&span class=&o&&(&/span&&span class=&s&&&1&&/span&&span class=&o&&);&/span&
&span class=&n&&s3&/span&&span class=&o&&.&/span&&span class=&na&&intern&/span&&span class=&o&&();&/span&
&span class=&n&&String&/span& &span class=&n&&s4&/span& &span class=&o&&=&/span& &span class=&s&&&11&&/span&&span class=&o&&;&/span&
&span class=&n&&System&/span&&span class=&o&&.&/span&&span class=&na&&out&/span&&span class=&o&&.&/span&&span class=&na&&println&/span&&span class=&o&&(&/span&&span class=&n&&s3&/span& &span class=&o&&==&/span& &span class=&n&&s4&/span&&span class=&o&&);&/span&
&span class=&o&&}&/span&
&/code&&/pre&&/div&&p&打印结果是&/p&&ul&&li&jdk7,8下false true&/li&&/ul&&p&调换一下位置后:&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&&span class=&kd&&public&/span& &span class=&kd&&static&/span& &span class=&kt&&void&/span& &span class=&nf&&main&/span&&span class=&o&&(&/span&&span class=&n&&String&/span&&span class=&o&&[]&/span& &span class=&n&&args&/span&&span class=&o&&)&/span& &span class=&o&&{&/span&
&span class=&n&&String&/span& &span class=&n&&s&/span& &span class=&o&&=&/span& &span class=&k&&new&/span& &span class=&n&&String&/span&&span class=&o&&(&/span&&span class=&s&&&1&&/span&&span class=&o&&);&/span&
&span class=&n&&String&/span& &span class=&n&&s2&/span& &span class=&o&&=&/span& &span class=&s&&&1&&/span&&span class=&o&&;&/span&
&span class=&n&&s&/span&&span class=&o&&.&/span&&span class=&na&&intern&/span&&span class=&o&&();&/span&
&span class=&n&&System&/span&&span class=&o&&.&/span&&span class=&na&&out&/span&&span class=&o&&.&/span&&span class=&na&&println&/span&&span class=&o&&(&/span&&span class=&n&&s&/span& &span class=&o&&==&/span& &span class=&n&&s2&/span&&span class=&o&&);&/span&
&span class=&n&&String&/span& &span class=&n&&s3&/span& &span class=&o&&=&/span& &span class=&k&&new&/span& &span class=&n&&String&/span&&span class=&o&&(&/span&&span class=&s&&&1&&/span&&span class=&o&&)&/span& &span class=&o&&+&/span& &span class=&k&&new&/span& &span class=&n&&String&/span&&span class=&o&&(&/span&&span class=&s&&&1&&/span&&span class=&o&&);&/span&
&span class=&n&&String&/span& &span class=&n&&s4&/span& &span class=&o&&=&/span& &span class=&s&&&11&&/span&&span class=&o&&;&/span&
&span class=&n&&s3&/span&&span class=&o&&.&/span&&span class=&na&&intern&/span&&span class=&o&&();&/span&
&span class=&n&&System&/span&&span class=&o&&.&/span&&span class=&na&&out&/span&&span class=&o&&.&/span&&span class=&na&&println&/span&&span class=&o&&(&/span&&span class=&n&&s3&/span& &span class=&o&&==&/span& &span class=&n&&s4&/span&&span class=&o&&);&/span&
&span class=&o&&}&/span&
&/code&&/pre&&/div&&p&打印结果为:&/p&&ul&&li&jdk7,8下false false&/li&&/ul&&p&文章中有很详细的解析,但我简单阅读了几次以后还是很懵逼。所以我知道了自己的知识点还存在漏洞,后面阅读了一下R大之前写过的文章:&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=http%3A//rednaxelafx.iteye.com/blog/comments& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&rednaxelafx.iteye.com/b&/span&&span class=&invisible&&log/774673#comments&/span&&span class=&ellipsis&&&/span&&/a&---请别再拿“String s = new String(&xyz&);创建了多少个String实例”来面试了吧&/li&&/ul&&p&看完了之后,就更加懵逼了。&/p&&p&后来,在zhihu上看到了这个回答:&/p&&ul&&li&&a href=&https://www.zhihu.com/question/& class=&internal&&&span class=&invisible&&https://www.&/span&&span class=&visible&&zhihu.com/question/5599&/span&&span class=&invisible&&4121&/span&&span class=&ellipsis&&&/span&&/a&---Java 中new String(&字面量&) 中 &字面量& 是何时进入字符串常量池的?&/li&&/ul&&p&结合网上资料和自己的思考,下面整理一下对常量池的理解~~&/p&&h2&1.6.1各个常量池的情况&/h2&&p&针对于jdk1.7之后:&/p&&ul&&li&常量池位于&b&堆中&/b&&/li&&li&运行时常量池位于&b&堆中&/b&&/li&&li&字符串常量池位于&b&堆中&/b&&/li&&/ul&&p&常量池存储的是:&/p&&ul&&li&字面量(Literal):文本字符串等----&用双引号引起来的字符串字面量都会进这里面&/li&&li&符号引用(Symbolic References)
- 类和接口的全限定名(Full Qualified Name)
- 字段的名称和描述符(Descriptor)
- 方法的名称和描述符&/li&&/ul&&blockquote&常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用,这部分内容将在&b&类加载后进入方法区的运行时常量池中存放&/b&---&来源:深入理解Java虚拟机 JVM高级特性与最佳实践(第二版)&/blockquote&&p&现在我们的运行时常量池只是换了一个位置(原本来方法区,现在在堆中),但可以明确的是:&b&类加载后,常量池中的数据会在运行时常量池中存放&/b&!&/p&&blockquote&HotSpot VM里,记录interned string的一个全局表叫做StringTable,它本质上就是个HashSet&String&。注意&b&它只存储对java.lang.String实例的引用,而不存储String对象的内容&/b&&/blockquote&&p&&b&字符串常量池只存储引用,不存储内容&/b&!&/p&&p&再来看一下我们的intern方法:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span& * When the intern method is invoked, if the pool already contains a
* string equal to this {@code String} object as determined by * the {@link #equals(Object)} method, then the string from the pool is * returned. Otherwise, this {@code String} object is added to the
* pool and a reference to this {@code String} object is returned.
&/code&&/pre&&/div&&ul&&li&&b&如果常量池中存在当前字符串,那么直接返回常量池中它的引用&/b&。&/li&&li&&b&如果常量池中没有此字符串, 会将此字符串引用保存到常量池中后, 再直接返回该字符串的引用&/b&!&/li&&/ul&&h2&1.6.2解析题目&/h2&&p&本来打算写注释的方式来解释的,但好像挺难说清楚的。我还是画图吧...&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&&span class=&kd&&public&/span& &span class=&kd&&static&/span& &span class=&kt&&void&/span& &span class=&nf&&main&/span&&span class=&o&&(&/span&&span class=&n&&String&/span&&span class=&o&&[]&/span& &span class=&n&&args&/span&&span class=&o&&)&/span& &span class=&o&&{&/span&
&span class=&n&&String&/span& &span class=&n&&s&/span& &span class=&o&&=&/span& &span class=&k&&new&/span& &span class=&n&&String&/span&&span class=&o&&(&/span&&span class=&s&&&1&&/span&&span class=&o&&);&/span&
&span class=&n&&s&/span&&span class=&o&&.&/span&&span class=&na&&intern&/span&&span class=&o&&();&/span&
&span class=&n&&String&/span& &span class=&n&&s2&/span& &span class=&o&&=&/span& &span class=&s&&&1&&/span&&span class=&o&&;&/span&
&span class=&n&&System&/span&&span class=&o&&.&/span&&span class=&na&&out&/span&&span class=&o&&.&/span&&span class=&na&&println&/span&&span class=&o&&(&/span&&span class=&n&&s&/span& &span class=&o&&==&/span& &span class=&n&&s2&/span&&span class=&o&&);&/span&&span class=&c1&&// false
&span class=&n&&System&/span&&span class=&o&&.&/span&&span class=&na&&out&/span&&span class=&o&&.&/span&&span class=&na&&println&/span&&span class=&o&&(&/span&&span class=&s&&&-----------关注公众号:Java3y-------------&&/span&&span class=&o&&);&/span&
&span class=&o&&}&/span&
&/code&&/pre&&/div&&p&第一句:&code&String s = new String(&1&);&/code&&/p&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-cc937fa11e26d89d59e924a1d7158eb0_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1061& data-rawheight=&613& class=&origin_image zh-lightbox-thumb& width=&1061& data-original=&https://pic1.zhimg.com/v2-cc937fa11e26d89d59e924a1d7158eb0_r.jpg&&&/figure&&p&&br&&/p&&p&第二句:&code&s.intern();&/code&发现字符串常量池中已经存在&1&字符串对象,直接&b&返回字符串常量池中对堆的引用(但没有接收)&/b&--&此时s引用还是指向着堆中的对象&/p&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-15dbc3fe4e48b09c4aabba960f902fcc_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1061& data-rawheight=&613& class=&origin_image zh-lightbox-thumb& width=&1061& data-original=&https://pic1.zhimg.com/v2-15dbc3fe4e48b09c4aabba960f902fcc_r.jpg&&&/figure&&p&&br&&/p&&p&第三句:&code&String s2 = &1&;&/code&发现字符串常量池&b&已经保存了该对象的引用&/b&了,直接返回字符串常量池对堆中字符串的引用&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-23cbee00e43da77a7a1a9_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1179& data-rawheight=&656& class=&origin_image zh-lightbox-thumb& width=&1179& data-original=&https://pic2.zhimg.com/v2-23cbee00e43da77a7a1a9_r.jpg&&&/figure&&p&&br&&/p&&p&很容易看到,&b&两条引用是不一样的!所以返回false&/b&。&/p&&hr&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&
&span class=&kd&&public&/span& &span class=&kd&&static&/span& &span class=&kt&&void&/span& &span class=&nf&&main&/span&&span class=&o&&(&/span&&span class=&n&&String&/span&&span class=&o&&[]&/span& &span class=&n&&args&/span&&span class=&o&&)&/span& &span class=&o&&{&/span&
&span class=&n&&System&/span&&span class=&o&&.&/span&&span class=&na&&out&/span&&span class=&o&&.&/span&&span class=&na&&println&/span&&span class=&o&&(&/span&&span class=&s&&&-----------关注公众号:Java3y-------------&&/span&&span class=&o&&);&/span&
&span class=&n&&String&/span& &span class=&n&&s3&/span& &span class=&o&&=&/span& &span class=&k&&new&/span& &span class=&n&&String&/span&&span class=&o&&(&/span&&span class=&s&&&1&&/span&&span class=&o&&)&/span& &span class=&o&&+&/span& &span class=&k&&new&/span& &span class=&n&&String&/span&&span class=&o&&(&/span&&span class=&s&&&1&&/span&&span class=&o&&);&/span&
&span class=&n&&s3&/span&&span class=&o&&.&/span&&span class=&na&&intern&/span&&span class=&o&&();&/span&
&span class=&n&&String&/span& &span class=&n&&s4&/span& &span class=&o&&=&/span& &span class=&s&&&11&&/span&&span class=&o&&;&/span&
&span class=&n&&System&/span&&span class=&o&&.&/span&&span class=&na&&out&/span&&span class=&o&&.&/span&&span class=&na&&println&/span&&span class=&o&&(&/span&&span class=&n&&s3&/span& &span class=&o&&==&/span& &span class=&n&&s4&/span&&span class=&o&&);&/span& &span class=&c1&&// true
&span class=&o&&}&/span&
&/code&&/pre&&/div&&p&第一句:&code&String s3 = new String(&1&) + new String(&1&);&/code&注意:此时**&11&对象并没有在字符串常量池中保存引用**。&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-664bffca76c9fafecb55a1_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1075& data-rawheight=&634& class=&origin_image zh-lightbox-thumb& width=&1075& data-original=&https://pic2.zhimg.com/v2-664bffca76c9fafecb55a1_r.jpg&&&/figure&&p&&br&&/p&&p&第二句:&code&s3.intern();&/code&发现&11&对象&b&并没有在字符串常量池中&/b&,于是将&11&对象在字符串常量池中&b&保存当前字符串的引用&/b&,并&b&返回&/b&当前字符串的引用(但没有接收)&/p&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-dd5aee92ae02c4d1f902e4_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1107& data-rawheight=&621& class=&origin_image zh-lightbox-thumb& width=&1107& data-original=&https://pic1.zhimg.com/v2-dd5aee92ae02c4d1f902e4_r.jpg&&&/figure&&p&&br&&/p&&p&第三句:&code&String s4 = &11&;&/code&发现字符串常量池已经存在引用了,直接返回(&b&拿到的也是与s3相同指向的引用&/b&)&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-c989ccc5f1cfef57ac16_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1126& data-rawheight=&627& class=&origin_image zh-lightbox-thumb& width=&1126& data-original=&https://pic3.zhimg.com/v2-c989ccc5f1cfef57ac16_r.jpg&&&/figure&&p&&br&&/p&&p&根据上述所说的:最后会返回true~~~&/p&&p&如果还是不太清楚的同学,可以试着接收一下&code&intern()&/code&方法的返回值,再看看上述的图,应该就可以理解了。&/p&&hr&&p&下面的就由各位来做做,看是不是掌握了:&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&
&span class=&kd&&public&/span& &span class=&kd&&static&/span& &span class=&kt&&void&/span& &span class=&nf&&main&/span&&span class=&o&&(&/span&&span class=&n&&String&/span&&span class=&o&&[]&/span& &span class=&n&&args&/span&&span class=&o&&)&/span& &span class=&o&&{&/span&
&span class=&n&&String&/span& &span class=&n&&s&/span& &span class=&o&&=&/span& &span class=&k&&new&/span& &span class=&n&&String&/span&&span class=&o&&(&/span&&span class=&s&&&1&&/span&&span class=&o&&);&/span&
&span class=&n&&String&/span& &span class=&n&&s2&/span& &span class=&o&&=&/span& &span class=&s&&&1&&/span&&span class=&o&&;&/span&
&span class=&n&&s&/span&&span class=&o&&.&/span&&span class=&na&&intern&/span&&span class=&o&&();&/span&
&span class=&n&&System&/span&&span class=&o&&.&/span&&span class=&na&&out&/span&&span class=&o&&.&/span&&span class=&na&&println&/span&&span class=&o&&(&/span&&span class=&n&&s&/span& &span class=&o&&==&/span& &span class=&n&&s2&/span&&span class=&o&&);&/span&&span class=&c1&&//false&/span&
&span class=&n&&String&/span& &span class=&n&&s3&/span& &span class=&o&&=&/span& &span class=&k&&new&/span& &span class=&n&&String&/span&&span class=&o&&(&/span&&span class=&s&&&1&&/span&&span class=&o&&)&/span& &span class=&o&&+&/span& &span class=&k&&new&/span& &span class=&n&&String&/span&&span class=&o&&(&/span&&span class=&s&&&1&&/span&&span class=&o&&);&/span&
&span class=&n&&String&/span& &span class=&n&&s4&/span& &span class=&o&&=&/span& &span class=&s&&&11&&/span&&span class=&o&&;&/span&
&span class=&n&&s3&/span&&span class=&o&&.&/span&&span class=&na&&intern&/span&&span class=&o&&();&/span&
&span class=&n&&System&/span&&span class=&o&&.&/span&&span class=&na&&out&/span&&span class=&o&&.&/span&&span class=&na&&println&/span&&span class=&o&&(&/span&&span class=&n&&s3&/span& &span class=&o&&==&/span& &span class=&n&&s4&/span&&span class=&o&&);&/span&&span class=&c1&&//false
&/code&&/pre&&/div&&p&还有:&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&
&span class=&kd&&public&/span& &span class=&kd&&static&/span& &span class=&kt&&void&/span& &span class=&nf&&main&/span&&span class=&o&&(&/span&&span class=&n&&String&/span&&span class=&o&&[]&/span& &span class=&n&&args&/span&&span class=&o&&)&/span& &span class=&o&&{&/span&
&span class=&n&&String&/span& &span class=&n&&s1&/span& &span class=&o&&=&/span& &span class=&k&&new&/span& &span class=&n&&String&/span&&span class=&o&&(&/span&&span class=&s&&&he&&/span&&span class=&o&&)&/span& &span class=&o&&+&/span& &span class=&k&&new&/span& &span class=&n&&String&/span&&span class=&o&&(&/span&&span class=&s&&&llo&&/span&&span class=&o&&);&/span&
&span class=&n&&String&/span& &span class=&n&&s2&/span& &span class=&o&&=&/span& &span class=&k&&new&/span& &span class=&n&&String&/span&&span class=&o&&(&/span&&span class=&s&&&h&&/span&&span class=&o&&)&/span& &span class=&o&&+&/span& &span class=&k&&new&/span& &span class=&n&&String&/span&&span class=&o&&(&/span&&span class=&s&&&ello&&/span&&span class=&o&&);&/span&
&span class=&n&&String&/span& &span class=&n&&s3&/span& &span class=&o&&=&/span& &span class=&n&&s1&/span&&span class=&o&&.&/span&&span class=&na&&intern&/span&&span class=&o&&();&/span&
&span class=&n&&String&/span& &span class=&n&&s4&/span& &span class=&o&&=&/span& &span class=&n&&s2&/span&&span class=&o&&.&/span&&span class=&na&&intern&/span&&span class=&o&&();&/span&
&span class=&n&&System&/span&&span class=&o&&.&/span&&span class=&na&&out&/span&&span class=&o&&.&/span&&span class=&na&&println&/span&&span class=&o&&(&/span&&span class=&n&&s1&/span& &span class=&o&&==&/span& &span class=&n&&s3&/span&&span class=&o&&);&/span&&span class=&c1&&// true
System.out.println(s1 == s4);// true
&/code&&/pre&&/div&&h2&1.7GC垃圾回收&/h2&&p&可以说GC垃圾回收是JVM中一个非常重要的知识点,应该非常详细去讲解的。但在我学习的途中,我已经发现了有很好的文章去讲解垃圾回收的了。&/p&&p&所以,这里我只简单介绍一下垃圾回收的东西,详细的可以到下面的面试题中查阅和最后给出相关的资料阅 读吧~&/p&&h2&1.7.1JVM垃圾回收简单介绍&/h2&&p&在C++中,我们知道创建出的对象是需要手动去delete掉的。我们Java程序运行在JVM中,JVM可以帮我们“自动”回收不需要的对象,对我们来说是十分方便的。&/p&&p&虽然说“自动”回收了我们不需要的对象,但如果我们想变强,就要变秃..不对,就要去了解一下它究竟是怎么干的,理论的知识有哪些。&/p&&p&首先,JVM回收的是&b&垃圾&/b&,垃圾就是我们程序中已经是不需要的了。垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还“存活”着,&b&哪些已经“死去”&/b&。判断哪些对象“死去”常用有两种方式:&/p&&ul&&li&引用计数法--&这种难以解决对象之间的循环引用的问题&/li&&li&&b&可达性分析算法&/b&--&主流的JVM采用的是这种方式&/li&&/ul&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-1f7d59d545cdb9e7d607_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&808& data-rawheight=&569& class=&origin_image zh-lightbox-thumb& width=&808& data-original=&https://pic4.zhimg.com/v2-1f7d59d545cdb9e7d607_r.jpg&&&/figure&&p&&br&&/p&&p&现在已经可以判断哪些对象已经“死去”了,我们现在要对这些“死去”的对象进行回收,回收也有好几种算法:&/p&&ul&&li&标记-清除算法&/li&&li&复制算法&/li&&li&标记-整理算法&/li&&li&分代收集算法&/li&&/ul&&p&(这些算法详情可看下面的面试题内容)~&/p&&p&无论是可达性分析算法,还是垃圾回收算法,JVM使用的都是&b&准确式GC&/b&。JVM是使用一组称为&b&OopMap&/b&的数据结构,来存储所有的对象引用(这样就不用遍历整个内存去查找了,空间换时间)。 并且不会将所有的指令都生成OopMap,只会在&b&安全点&/b&上生成OopMap,在&b&安全区域&/b&上开始GC。&/p&&ul&&li&在OopMap的协助下,HotSpot可以&b&快速且准确地&/b&完成GC Roots枚举(可达性分析)。&/li&&/ul&&p&上面所讲的垃圾收集算法只能算是&b&方法论&/b&,落地实现的是&b&垃圾收集器&/b&:&/p&&ul&&li&Serial收集器&/li&&li&ParNew收集器&/li&&li&Parallel Scavenge收集器&/li&&li&Serial Old收集器&/li&&li&Parallel Old收集器&/li&&li&CMS收集器&/li&&li&G1收集器&/li&&/ul&&p&上面这些收集器大部分是可以互相&b&组合使用&/b&的&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-bccacb68a46497cbcf8edb_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&719& data-rawheight=&696& class=&origin_image zh-lightbox-thumb& width=&719& data-original=&https://pic4.zhimg.com/v2-bccacb68a46497cbcf8edb_r.jpg&&&/figure&&p&&br&&/p&&h2&1.8JVM参数与调优&/h2&&p&很多做过JavaWeb项目(ssh/ssm)这样的同学可能都会遇到过OutOfMemory这样的错误。一般解决起来也很方便,在启动的时候加个参数就行了。&/p&&p&上面也说了很多关于JVM的东西---&JVM对内存的划分啊,JVM各种的垃圾收集器啊。&/p&&p&内存的分配的大小啊,使用哪个收集器啊,这些都可以由我们&b&根据需求,现实情况来指定&/b&的,这里就不详细说了,等真正用到的时候才回来填坑吧~~~~&/p&&p&参考资料:&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=http%3A//www.cnblogs.com/redcreen/archive//2037057.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&cnblogs.com/redcreen/ar&/span&&span class=&invisible&&chive//2037057.html&/span&&span class=&ellipsis&&&/span&&/a&---JVM系列三:JVM参数设置、分析&/li&&/ul&&h2&二、JVM面试题&/h2&&p&拿些常见的JVM面试题来做做,&b&加深一下理解和查缺补漏&/b&:&/p&&ul&&li&1、详细jvm内存模型&/li&&li&2、讲讲什么情况下回出现内存溢出,内存泄漏?&/li&&li&3、说说Java线程栈&/li&&li&4、JVM 年轻代到年老代的晋升过程的判断条件是什么呢?&/li&&li&5、JVM 出现 fullGC 很频繁,怎么去线上排查问题?&/li&&li&6、类加载为什么要使用双亲委派模式,有没有什么场景是打破了这个模式?&/li&&li&7、类的实例化顺序&/li&&li&8、JVM垃圾回收机制,何时触发MinorGC等操作&/li&&li&9、JVM 中一次完整的 GC 流程(从 ygc 到 fgc)是怎样的&/li&&li&10、各种回收器,各自优缺点,重点CMS、G1&/li&&li&11、各种回收算法&/li&&li&12、OOM错误,stackoverflow错误,permgen space错误&/li&&/ul&&p&题目来源:&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=https%3A//www.jianshu.com/p/a07d1d4004b0& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&jianshu.com/p/a07d1d400&/span&&span class=&invisible&&4b0&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&2.1详细jvm内存模型&/h2&&p&根据 JVM 规范,JVM 内存共分为虚拟机栈、堆、方法区、程序计数器、本地方法栈五个部分。&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-addabb420eee2f6b_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1108& data-rawheight=&546& class=&origin_image zh-lightbox-thumb& width=&1108& data-original=&https://pic4.zhimg.com/v2-addabb420eee2f6b_r.jpg&&&/figure&&p&&br&&/p&&p&具体&b&可能会&/b&聊聊jdk1.7以前的PermGen(永久代),替换成Metaspace(元空间)&/p&&ul&&li&原本永久代存储的数据:符号引用(Symbols)转移到了native heap;字面量(interned strings)转移到了java heap;类的静态变量(class statics)转移到了java heap&/li&&li&Metaspace(元空间)存储的是类的元数据信息(metadata)&/li&&li&元空间的本质和永久代类似,都是&b&对JVM规范中方法区的实现&/b&。不过元空间与永久代之间最大的区别在于:&b&元空间并不在虚拟机中,而是使用本地内存&/b&。&/li&&li&&b&替换的好处&/b&:一、字符串存在永久代中,容易出现性能问题和内存溢出。二、永久代会为 GC 带来不必要的复杂度,并且回收效率偏低&/li&&/ul&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-4de571b2631dfae42ad5f6_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&589& data-rawheight=&403& class=&origin_image zh-lightbox-thumb& width=&589& data-original=&https://pic3.zhimg.com/v2-4de571b2631dfae42ad5f6_r.jpg&&&/figure&&p&&br&&/p&&p&图片来源:&a href=&http://link.zhihu.com/?target=https%3A//blog.csdn.net/tophawk/article/details/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&blog.csdn.net/tophawk/a&/span&&span class=&invisible&&rticle/details/&/span&&span class=&ellipsis&&&/span&&/a&&/p&&p&参考资料:&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=https%3A//www.cnblogs.com/paddix/p/5309550.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&cnblogs.com/paddix/p/53&/span&&span class=&invisible&&09550.html&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&2.2讲讲什么情况下回出现内存溢出,内存泄漏?&/h2&&p&内存泄漏的原因很简单:&/p&&ul&&li&&b&对象是可达的&/b&(一直被引用)&/li&&li&但是对象&b&不会被使用&/b&&/li&&/ul&&p&常见的内存泄漏例子:&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span& &span class=&kd&&public&/span& &span class=&kd&&static&/span& &span class=&kt&&void&/span& &span class=&nf&&main&/span&&span class=&o&&(&/span&&span class=&n&&String&/span&&span class=&o&&[]&/span& &span class=&n&&args&/span&&span class=&o&&)&/span& &span class=&o&&{&/span&
&span class=&n&&Set&/span& &span class=&n&&set&/span& &span class=&o&&=&/span& &span class=&k&&new&/span& &span class=&n&&HashSet&/span&&span class=&o&&();&/span&
&span class=&k&&for&/span& &span class=&o&&(&/span&&span class=&kt&&int&/span& &span class=&n&&i&/span& &span class=&o&&=&/span& &span class=&mi&&0&/span&&span class=&o&&;&/span& &span class=&n&&i&/span& &span class=&o&&&&/span& &span class=&mi&&10&/span&&span class=&o&&;&/span& &span class=&n&&i&/span&&span class=&o&&++)&/span& &span class=&o&&{&/span&
&span class=&n&&Object&/span& &span class=&n&&object&/span& &span class=&o&&=&/span& &span class=&k&&new&/span& &span class=&n&&Object&/span&&span class=&o&&();&/span&
&span class=&n&&set&/span&&span class=&o&&.&/span&&span class=&na&&add&/span&&span class=&o&&(&/span&&span class=&n&&object&/span&&span class=&o&&);&/span&
&span class=&c1&&// 设置为空,这对象我不再用了
&span class=&n&&object&/span& &span class=&o&&=&/span& &span class=&kc&&null&/span&&span class=&o&&;&/span&
&span class=&o&&}&/span&
&span class=&c1&&// 但是set集合中还维护这obj的引用,gc不会回收object对象
&span class=&n&&System&/span&&span class=&o&&.&/span&&span class=&na&&out&/span&&span class=&o&&.&/span&&span class=&na&&println&/span&&span class=&o&&(&/span&&span class=&n&&set&/span&&span class=&o&&);&/span&
&span class=&o&&}&/span&
&/code&&/pre&&/div&&p&解决这个内存泄漏问题也很简单,将set设置为null,那就可以避免&b&上诉&/b&内存泄漏问题了。其他内存泄漏得一步一步分析了。&/p&&p&内存泄漏参考资料:&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=https%3A//www.ibm.com/developerworks/cn/java/l-JavaMemoryLeak/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&ibm.com/developerworks/&/span&&span class=&invisible&&cn/java/l-JavaMemoryLeak/&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&p&内存溢出的原因:&/p&&ul&&li&内存泄露导致堆栈内存不断增大,从而引发内存溢出。&/li&&li&大量的jar,class文件加载,装载类的空间不够,溢出&/li&&li&操作大量的对象导致堆内存空间已经用满了,溢出&/li&&li&nio直接操作内存,内存过大导致溢出&/li&&/ul&&p&解决:&/p&&ul&&li&查看程序是否存在内存泄漏的问题&/li&&li&设置参数加大空间&/li&&li&代码中是否存在死循环或循环产生过多重复的对象实体、&/li&&li&查看是否使用了nio直接操作内存。&/li&&/ul&&p&参考资料:&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=https%3A//www.cnblogs.com/bingosblog/p/6661527.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&cnblogs.com/bingosblog/&/span&&span class=&invisible&&p/6661527.html&/span&&span class=&ellipsis&&&/span&&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//www.importnew.com/14604.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&importnew.com/14604.htm&/span&&span class=&invisible&&l&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&2.3说说线程栈&/h2&&blockquote&这里的线程栈应该指的是虚拟机栈吧...&/blockquote&&p&JVM规范让&b&每个Java线程&/b&拥有自己的&b&独立的JVM栈&/b&,也就是Java方法的调用栈。&/p&&p&当方法调用的时候,会生成一个&b&栈帧&/b&。栈帧是保存在虚拟机栈中的,栈帧存储了方法的&b&局部变量表、操作数栈&/b&、动态连接和方法返回地址等信息&/p&&p&线程运行过程中,&b&只有一个栈帧是处于活跃状态&/b&,称为“当前活跃栈帧”,当前活动栈帧始终是虚拟机栈的&b&栈顶元素&/b&。&/p&&p&通过&b&jstack&/b&工具查看线程状态&/p&&p&参考资料:&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=http%3A//wangwengcn.iteye.com/blog/1622195& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&wangwengcn.iteye.com/bl&/span&&span class=&invisible&&og/1622195&/span&&span class=&ellipsis&&&/span&&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=https%3A//www.cnblogs.com/Codenewbie/p/6184898.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&cnblogs.com/Codenewbie/&/span&&span class=&invisible&&p/6184898.html&/span&&span class=&ellipsis&&&/span&&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=https%3A//blog.csdn.net/u/article/details/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&blog.csdn.net/u&/span&&span class=&invisible&&4/article/details/&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&2.4JVM 年轻代到年老代的晋升过程的判断条件是什么呢?&/h2&&ol&&li&部分对象会在From和To区域中复制来复制去,&b&如此交换15次&/b&(由JVM参数MaxTenuringThreshold决定,这个参数默认是15),最终如果还是存活,就存入到老年代。&/li&&li&如果&b&对象的大小大于Eden的二分之一会直接分配在old&/b&,如果old也分配不下,会做一次majorGC,如果小于eden的一半但是没有足够的空间,就进行minorgc也就是新生代GC。&/li&&li&minor gc后,survivor仍然放不下,则放到老年代&/li&&li&动态年龄判断 ,大于等于某个年龄的对象超过了survivor空间一半 ,大于等于某个年龄的对象直接进入老年代&/li&&/ol&&h2&2.5JVM 出现 fullGC 很频繁,怎么去线上排查问题&/h2&&p&这题就依据full GC的触发条件来做:&/p&&ul&&li&如果有perm gen的话(jdk1.8就没了),&b&要给perm gen分配空间,但没有足够的空间时&/b&,会触发full gc。
- 所以看看是不是perm gen区的值设置得太小了。&/li&&li&&code&System.gc()&/code&方法的调用
- 这个一般没人去调用吧~~~&/li&&li& 当&b&统计&/b&得到的Minor GC晋升到旧生代的平均大小&b&大于老年代的剩余空间&/b&,则会触发full gc(这就可以从多个角度上看了)
- 是不是&b&频繁创建了大对象(也有可能eden区设置过小)&/b&(大对象直接分配在老年代中,导致老年代空间不足---&从而频繁gc)
- 是不是&b&老年代的空间设置过小了&/b&(Minor GC几个对象就大于老年代的剩余空间了)&/li&&/ul&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-7ca34c8ecb_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1048& data-rawheight=&303& class=&origin_image zh-lightbox-thumb& width=&1048& data-original=&https://pic4.zhimg.com/v2-7ca34c8ecb_r.jpg&&&/figure&&p&&br&&/p&&h2&2.6类加载为什么要使用双亲委派模式,有没有什么场景是打破了这个模式?&/h2&&p&双亲委托模型的重要用途是为了解决类载入过程中的&b&安全性问题&/b&。&/p&&ul&&li&假设有一个开发者自己编写了一个名为&code&java.lang.Object&/code&的类,想借此欺骗JVM。现在他要使用自定义&code&ClassLoader&/code&来加载自己编写的&code&java.lang.Object&/code&类。&/li&&li&然而幸运的是,双亲委托模型不会让他成功。因为JVM会优先在&code&Bootstrap ClassLoader&/code&的路径下找到&code&java.lang.Object&/code&类,并载入它&/li&&/ul&&p&Java的类加载是否一定遵循双亲委托模型?&/p&&ul&&li&在实际开发中,我们可以&b&通过自定义ClassLoader,并重写父类的loadClass方法&/b&,来打破这一机制。&/li&&li&SPI就是打破了双亲委托机制的(SPI:服务提供发现)。SPI资料:
- &a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&&span class=&invisible&&https://&/span&&span class=&visible&&zhuanlan.zhihu.com/p/28&/span&&span class=&invisible&&909673&/span&&span class=&ellipsis&&&/span&&/a&
- &a href=&http://link.zhihu.com/?target=https%3A//www.cnblogs.com/huzi007/p/6679215.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&cnblogs.com/huzi007/p/6&/span&&span class=&invisible&&679215.html&/span&&span class=&ellipsis&&&/span&&/a&
- &a href=&http://link.zhihu.com/?target=https%3A//blog.csdn.net/sigangjun/article/details/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&blog.csdn.net/sigangjun&/span&&span class=&invisible&&/article/details/&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&p&参考资料:&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=https%3A//blog.csdn.net/markzy/article/details/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&blog.csdn.net/markzy/ar&/span&&span class=&invisible&&ticle/details/&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&2.7类的实例化顺序&/h2&&ul&&li&1. 父类静态成员和静态初始化块 ,按在代码中出现的顺序依次执行&/li&&li&2. 子类静态成员和静态初始化块 ,按在代码中出现的顺序依次执行&/li&&li&3. 父类实例成员和实例初始化块 ,按在代码中出现的顺序依次执行&/li&&li&4. 父类构造方法&/li&&li&5. 子类实例成员和实例初始化块 ,按在代码中出现的顺序依次执行&/li&&li&6. 子类构造方法&/li&&/ul&&p&检验一下是不是真懂了:&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&&span class=&kd&&class&/span& &span class=&nc&&Dervied&/span& &span class=&kd&&extends&/span& &span class=&n&&Base&/span& &span class=&o&&{&/span&
&span class=&kd&&private&/span& &span class=&n&&String&/span& &span class=&n&&name&/span& &span class=&o&&=&/span& &span class=&s&&&Java3y&&/span&&span class=&o&&;&/span&
&span class=&kd&&public&/span& &span class=&nf&&Dervied&/span&&span class=&o&&()&/span& &span class=&o&&{&/span&
&span class=&n&&tellName&/span&&span class=&o&&();&/span&
&span class=&n&&printName&/span&&span class=&o&&();&/span&
&span class=&o&&}&/span&
&span class=&kd&&public&/span& &span class=&kt&&void&/span& &span class=&nf&&tellName&/span&&span class=&o&&()&/span& &span class=&o&&{&/span&
&span class=&n&&System&/span&&span class=&o&&.&/span&&span class=&na&&out&/span&&span class=&o&&.&/span&&span class=&na&&println&/span&&span class=&o&&(&/span&&span class=&s&&&Dervied tell name: &&/span& &span class=&o&&+&/span& &span class=&n&&name&/span&&span class=&o&&);&/span&
&span class=&o&&}&/span&
&span class=&kd&&public&/span& &span class=&kt&&void&/span& &span class=&nf&&printName&/span&&span class=&o&&()&/span& &span class=&o&&{&/span&
&span class=&n&&System&/span&&span class=&o&&.&/span&&span class=&na&&out&/span&&span class=&o&&.&/span&&span class=&na&&println&/span&&span class=&o&&(&/span&&span class=&s&&&Dervied print name: &&/span& &span class=&o&&+&/span& &span class=&n&&name&/span&&span class=&o&&);&/span&
&span class=&o&&}&/span&
&span class=&kd&&public&/span& &span class=&kd&&static&/span& &span class=&kt&&void&/span& &span class=&nf&&main&/span&&span class=&o&&(&/span&&span class=&n&&String&/span&&span class=&o&&[]&/span& &span class=&n&&args&/span&&span class=&o&&)&/span& &span class=&o&&{&/span&
&span class=&k&&new&/span& &span class=&n&&Dervied&/span&&span class=&o&&();&/span&
&span class=&o&&}&/span&
&span class=&o&&}&/span&
&span class=&kd&&class&/span& &span class=&nc&&Base&/span& &span class=&o&&{&/span&
&span class=&kd&&private&/span& &span class=&n&&String&/span& &span class=&n&&name&/span& &span class=&o&&=&/span& &span class=&s&&&公众号&&/span&&span class=&o&&;&/span&
&span class=&kd&&public&/span& &span class=&nf&&Base&/span&&span class=&o&&()&/span& &span class=&o&&{&/span&
&span class=&n&&tellName&/span&&span class=&o&&();&/span&
&span class=&n&&printName&/span&&span class=&o&&();&/span&
&span class=&o&&}&/span&
&span class=&kd&&public&/span& &span class=&kt&&void&/span& &span class=&nf&&tellName&/span&&span class=&o&&()&/span& &span class=&o&&{&/span&
&span class=&n&&System&/span&&span class=&o&&.&/span&&span class=&na&&out&/span&&span class=&o&&.&/span&&span class=&na&&println&/span&&span class=&o&&(&/span&&span class=&s&&&Base tell name: &&/span& &span class=&o&&+&/span& &span class=&n&&name&/span&&span class=&o&&);&/span&
&span class=&o&&}&/span&
&span class=&kd&&public&/span& &span class=&kt&&void&/span& &span class=&nf&&printName&/span&&span class=&o&&()&/span& &span class=&o&&{&/span&
&span class=&n&&System&/span&&span class=&o&&.&/span&&span class=&na&&out&/span&&span class=&o&&.&/span&&span class=&na&&println&/span&&span class=&o&&(&/span&&span class=&s&&&Base print name: &&/span& &span class=&o&&+&/span& &span class=&n&&name&/span&&span class=&o&&);&/span&
&span class=&o&&}&/span&
&span class=&o&&}&/span&
&/code&&/pre&&/div&&p&输出数据:&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&&span class=&n&&Dervied&/span& &span class=&n&&tell&/span& &span class=&n&&name&/span&&span class=&o&&:&/span& &span class=&kc&&null&/span&
&span class=&n&&Dervied&/span& &span class=&n&&print&/span& &span class=&n&&name&/span&&span class=&o&&:&/span& &span class=&kc&&null&/span&
&span class=&n&&Dervied&/span& &span class=&n&&tell&/span& &span class=&n&&name&/span&&span class=&o&&:&/span& &span class=&n&&Java3y&/span&
&span class=&n&&Dervied&/span& &span class=&n&&print&/span& &span class=&n&&name&/span&&span class=&o&&:&/span& &span class=&n&&Java3y&/span&
&/code&&/pre&&/div&&p&第一次做错的同学点个赞,加个关注不过分吧(hahaha&/p&&h2&2.8JVM垃圾回收机制,何时触发MinorGC等操作&/h2&&p&当young gen中的eden区分配满的时候触发MinorGC(新生代的空间不够放的时候).&/p&&h2&2.9JVM 中一次完整的 GC 流程(从 ygc 到 fgc)是怎样的&/h2&&p&这题不是很明白意思(水平有限...如果知道这题的意思可在评论区留言呀~~)&/p&&ul&&li&因为按我的理解:执行fgc是不会执行ygc的呀~~&/li&&/ul&&blockquote&YGC和FGC是什么 &/blockquote&&ul&&li&YGC :&b&对新生代堆进行gc&/b&。频率比较高,因为大部分对象的存活寿命较短,在新生代里被回收。性能耗费较小。&/li&&li&FGC :&b&全堆范围的gc&/b&。默认堆空间使用到达80%(可调整)的时候会触发fgc。以我们生产环境为例,一般比较少会触发fgc,有时10天或一周左右会有一次。&/li&&/ul&&blockquote&什么时候执行YGC和FGC&/blockquote&&ul&&li&a.eden空间不足,执行 young gc&/li&&li&b.old空间不足,perm空间不足,调用方法&code&System.gc()&/code& ,ygc时的悲观策略, dump live的内存信息时(jmap –dump:live),都会执行full gc&/li&&/ul&&h2&2.10各种回收算法&/h2&&p&GC最基础的算法有三种:&/p&&ul&&li&标记 -清除算法&/li&&li&复制算法&/li&&li&标记-压缩算法&/li&&li&我们常用的垃圾回收器一般都采用&b&分代收集算法&/b&(其实就是组合上面的算法,

我要回帖

更多关于 apacheapollo集群 的文章

 

随机推荐