出现异常之后后续代码执行情况
参见大佬博客:http://www.cnblogs.com/wangyingli/p/5912269.html
总结:1.方法中某一行出现异常或者throws new Exception()并且没有捕获异常则后续的代码不会继续执行。
2.如果抛异常中的某一行代码抛异常后捕获了,则后续的代码会继续执行。
3.catch()中语句会在finally()之前执行,而finally()是在return语句执行之前执行。
出现异常之后后续代码执行情况
参见大佬博客:http://www.cnblogs.com/wangyingli/p/5912269.html
总结:1.方法中某一行出现异常或者throws new Exception()并且没有捕获异常则后续的代码不会继续执行。
2.如果抛异常中的某一行代码抛异常后捕获了,则后续的代码会继续执行。
3.catch()中语句会在finally()之前执行,而finally()是在return语句执行之前执行。
转载于:https://www.cnblogs.com/chaojibaidu/p/10871304.html
静态代码块
在java中,用一个大括号括起来的一行或多行代码叫代码块,而被static关键字修饰的代码块即为静态代码块。静态代码块只在类加载(类加载:当程序的运行,需要用到某一个类且这个类只是定义了还没有被加载到内存空间时,会进行加载,连接,初始化三个步骤来进行类加载)的时候自动执行,且只执行一次。
package test; public class StaticTest2 { //创建一个静态代码块 static{ System.out.println("静态代码块执行了"); } //创建一个非静态代码块 { System.out.println("非静态代码块执行了"); } //创建一个构造方法 StaticTest2(){ System.out.println("构造方法"); } public static void main(String[] args) { } }
这段代码运行的时候,最终的打印结果只有静态代码块在类加载的时候执行了,运行结果如下图
非静态代码块
非静态代码块是在创建类对象的时候运行,只要创建一次类对象,就会运行一次。且非静态代码块的运行是在构造方法之前执行。
package test; public class StaticTest2 { //创建一个静态代码块 static{ System.out.println("静态代码块执行了"); } //创建一个非静态代码块 { System.out.println("非静态代码块执行了"); } //创建一个构造方法 StaticTest2(){ System.out.println("构造方法"); } public static void main(String[] args) { StaticTest2 st=new StaticTest2(); } }
运行结果如下,注意是先运行静态代码块,因为静态代码块在类加载的时候就已经执行了。类加载后才会进行实例化,创建类对象,才会执行非静态代码块,最后才执行构造方法。运行结果如下图
本文是为java内存溢出系列第2小篇。
Java运行时环境内置了 垃圾收集(GC) 模块. 上一代的很多编程语言中并没有自动内存回收机制, 需要程序员手工编写代码来进行内存分配和释放, 以重复利用堆内存。
在Java程序中, 只需要关心内存分配就行。如果某块内存不再使用, 垃圾收集(Garbage Collection) 模块会自动执行清理。GC的详细原理请参考 GC性能优化 系列文章, 一般来说, JVM内置的垃圾收集算法就能够应对绝大多数的业务场景。
java.lang.OutOfMemoryError: GC overhead limit exceeded 这种情况发生的原因是, 程序基本上耗尽了所有的可用内存, GC也清理不了。
原因分析
JVM抛出 java.lang.OutOfMemoryError: GC overhead limit exceeded 错误就是发出了这样的信号: 执行垃圾收集的时间比例太大, 有效的运算量太小. 默认情况下, 如果GC花费的时间超过 98%, 并且GC回收的内存少于 2%, JVM就会抛出这个错误。
注意, java.lang.OutOfMemoryError: GC overhead limit exceeded 错误只在连续多次 GC 都只回收了不到2%的极端情况下才会抛出。假如不抛出
GC overhead limit
错误会发生什么情况呢? 那就是GC清理的这么点内存很快会再次填满, 迫使GC再次执行. 这样就形成恶性循环, CPU使用率一直是100%, 而GC却没有任何成果. 系统用户就会看到系统卡死 - 以前只需要几毫秒的操作, 现在需要好几分钟才能完成。这也是一个很好的 快速失败原则 的案例。
示例
以下代码在无限循环中往 Map 里添加数据。这会导致 “GC overhead limit exceeded” 错误:
package com.cncounter.rtime;import java.util.Map;import java.util.Random;public class TestWrapper {public static void main(String args[]) throws Exception { Map map = System.getProperties(); Random r = new Random();while (true) {map.put(r.nextInt(), "value"); } }}
配置JVM参数:
-Xmx12m
。执行时产生的错误信息如下所示:Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceededat java.util.Hashtable.addEntry(Hashtable.java:435)at java.util.Hashtable.put(Hashtable.java:476)at com.cncounter.rtime.TestWrapper.main(TestWrapper.java:11)
你碰到的错误信息不一定就是这个。确实, 我们执行的JVM参数为:
java -Xmx12m -XX:+UseParallelGC TestWrapper
很快就看到了 java.lang.OutOfMemoryError: GC overhead limit exceeded 错误提示消息。但实际上这个示例是有些坑的. 因为配置不同的堆内存大小, 选用不同的GC算法, 产生的错误信息也不相同。例如,当Java堆内存设置为10M时:
java -Xmx10m -XX:+UseParallelGC TestWrapper
DEBUG模式下错误信息如下所示:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap spaceat java.util.Hashtable.rehash(Hashtable.java:401)at java.util.Hashtable.addEntry(Hashtable.java:425)at java.util.Hashtable.put(Hashtable.java:476)at com.cncounter.rtime.TestWrapper.main(TestWrapper.java:11)
读者应该试着修改参数, 执行看看具体。错误提示以及堆栈信息可能不太一样。
这里在 Map 进行
rehash
时抛出了 java.lang.OutOfMemoryError: Java heap space 错误消息. 如果使用其他 垃圾收集算法, 比如 -XX:+UseConcMarkSweepGC, 或者 -XX:+UseG1GC, 错误将被默认的 exception handler 所捕获, 但是没有 stacktrace 信息, 因为在创建 Exception 时 没办法填充stacktrace信息。例如配置:
-Xmx12m -XX:+UseG1GC
在Win7x64, Java8环境运行, 产生的错误信息为:
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"
建议读者修改内存配置, 以及垃圾收集算法进行测试。
这些真实的案例表明, 在资源受限的情况下, 无法准确预测程序会死于哪种具体的原因。所以在这类错误面前, 不能绑死某种特定的错误处理顺序。
解决方案
有一种应付了事的解决方案, 就是不想抛出 “java.lang.OutOfMemoryError: GC overhead limit exceeded” 错误信息, 则添加下面启动参数:
// 不推荐-XX:-UseGCOverheadLimit
我们强烈建议不要指定该选项: 因为这不能真正地解决问题,只能推迟一点
out of memory
错误发生的时间,到最后还得进行其他处理。指定这个选项, 会将原来的 java.lang.OutOfMemoryError: GC overhead limit exceeded 错误掩盖,变成更常见的 java.lang.OutOfMemoryError: Java heap space 错误消息。需要注意: 有时候触发 GC overhead limit 错误的原因, 是因为分配给JVM的堆内存不足。这种情况下只需要增加堆内存大小即可。
在大多数情况下, 增加堆内存并不能解决问题。例如程序中存在内存泄漏, 增加堆内存只能推迟产生 java.lang.OutOfMemoryError: Java heap space 错误的时间。
当然, 增大堆内存, 还有可能会增加 GC pauses 的时间, 从而影响程序的 吞吐量或延迟。
如果想从根本上解决问题, 则需要排查内存分配相关的代码. 简单来说, 需要回答以下问题:
哪类对象占用了最多内存?
这些对象是在哪部分代码中分配的。
要搞清这一点, 可能需要好几天时间。下面是大致的流程:
获得在生产服务器上执行堆转储(heap dump)的权限。“转储”(Dump)是堆内存的快照, 可用于后续的内存分析. 这些快照中可能含有机密信息, 例如密码、信用卡账号等, 所以有时候, 由于企业的安全限制, 要获得生产环境的堆转储并不容易。
在适当的时间执行堆转储。一般来说,内存分析需要比对多个堆转储文件, 假如获取的时机不对, 那就可能是一个“废”的快照. 另外, 每执行一次堆转储, 就会对JVM进行一次“冻结”, 所以生产环境中,不能执行太多的Dump操作,否则系统缓慢或者卡死,你的麻烦就大了。
用另一台机器来加载Dump文件。如果出问题的JVM内存是8GB, 那么分析 Heap Dump 的机器内存一般需要大于 8GB. 然后打开转储分析软件(我们推荐Eclipse MAT , 当然你也可以使用其他工具)。
检测快照中占用内存最大的 GC roots。详情请参考: Solving OutOfMemoryError (part 6) – Dump is not a waste。这对新手来说可能有点困难, 但这也会加深你对堆内存结构以及 navigation 机制的理解。
接下来, 找出可能会分配大量对象的代码. 如果对整个系统非常熟悉, 可能很快就能定位问题。运气不好的话,就只有加班加点来进行排查了。
推荐 Plumbr, the only Java monitoring solution with automatic root cause detection。Plumbr 能捕获所有的 java.lang.OutOfMemoryError , 并找出其他的性能问题, 例如最消耗内存的数据结构等等。
Plumbr 在后台负责收集数据 —— 包括堆内存使用情况(只统计对象分布图, 不涉及实际数据),以及在堆转储中不容易发现的各种问题。如果发生 java.lang.OutOfMemoryError , 还能在不停机的情况下, 做必要的数据处理. 下面是Plumbr 对一个 java.lang.OutOfMemoryError 的提醒:
强大吧, 不需要其他工具和分析, 就能直接看到:
哪类对象占用了最多的内存(此处是 271 个 com.example.map.impl.PartitionContainer 实例, 消耗了 173MB 内存, 而堆内存只有 248MB)
这些对象在何处创建(大部分是在 MetricManagerImpl 类中,第304行处)
当前是谁在引用这些对象(从 GC root 开始的完整引用链)
得知这些信息, 就可以定位到问题的根源, 例如是当地精简数据结构/模型, 只占用必要的内存即可。
当然, 根据内存分析的结果, 以及Plumbr生成的报告, 如果发现对象占用的内存很合理, 也不需要修改源代码的话, 那就增大堆内存吧。在这种情况下,修改JVM启动参数, (按比例)增加下面的值:
java -Xmx1024m com.yourcompany.YourClass`
这里配置了最大堆内存为
1GB
。请根据实际情况修改这个值. 如果 JVM 还是会抛出 OutOfMemoryError, 那么你可能还需要查询手册, 或者借助工具再次进行分析和诊断。1.OutOfMemoryError之Java heap space
2.OutOfMemoryError之GC overhead limit exceeded
3.OutOfMemoryError之Permgen space
4.OutOfMemoryError之Metaspace
5.OutOfMemoryError之Unable to create new native thread
6.OutOfMemoryError之Out of swap space?
7.OutOfMemoryError之Requested array size exceeds VM limit
8.OutOfMemoryError之Kill process or sacrifice child
相关知识:https://blog.csdn.net/mokexfdgh/article/category/8092196
myeclipse的使用
debug
debug的调试模式(断点调试模式):
通过设置一个断点(双击行号,可有多个断点)可以使程序运行(debug as)停止在某一行,
然后可以向下单步执行且可以观察变量值,用于调试程序
单步执行:step over(快捷键为F6)
当前断点调试结束:resume(快捷键为F8,若后面没有断点则程序直接运行结束)
debug查看方法源代码:在方法调用处设置断点,debug点击step into(F7),返回step return常用快捷键
(1)ALT+/:代码提示
(2)Ctrl+1:快速导包
(3)Ctrl+/:单行注释(去掉:Ctr+/)
(4)Ctrl+Shift+/:多行注释(去掉:Ctrl+Shift+\)
(5)Ctrl+D:删除行
(6)Ctrl+Shift+F:代码的格式化(缩进)
(7)Ctrl+S:保存
…单元测试(junit)
单元测试:测试对象为类中的方法
注:junit不是javase的一部分,需要导入jar包,且单元测试方法,方法命名public void 方法名(){}//不能有参数,返回值创建一个source文件夹,在里面创建需要测试的类的同名的包和类,并在其中写测试方法,如下:
class demo{ //需要导包 @Test /*@Ignore:此方法不进行单元测试 *@Before:在每个方法之前运行 *@After:在每个方法之后运行 */ public void test(){ Demo demo = new Demo(); demo.test1(2,3); } //测试方法使用注解方式运行:run as--junit test //绿条为测试不通过,红条则不通过 //断言:Assert.asserEquals("测试期望的值","方法运行的实际值") }
基础知识补充
枚举类
enum Color{//关键字:enum RED,GREEN,YELLOW;//枚举类对象 //RED("red"); //private Color(String s){} } //相当于 class Color1{ private Color1(){}//构造方法私有,不能通过其创建实例 public static final Color1 RED = new Color1(); public static final Color1 GREEN = new Color1(); public static final Color1 YELLOW = new Color1(); }//当枚举类中有抽象方法时,每个枚举对象都需要实现抽象方法
常用方法:
name():返回枚举的名称
ordinal():枚举的下标(从0开始)
valueOf(Class enumType,String name):得到枚举对象
不在api中的方法:
valueof(String name):转换枚举对象
values():获取所有枚举对象数组自动拆装箱?
装箱:把基本的数据类型转换成包装类
拆箱:把包装类转换成基本的数据类型
*jdk向下兼容Integer i = 10;//自动装箱 int m = i;//自动拆箱
八种基本数据类型对应的包装类:
int->Integer
char->Character
其它的都是基本数据类型名称的首字母大写增强for循环
底层就是Iterable迭代器,为了替代迭代器而出现
for(变量类型 变量 : 要遍历的集合){}
数组:实现Iterable接口可以使用增强for循环
可用增强for循环的集合:List,Set(map不能使用)可变参数
实现多个方法,方法里面的处理基本相同,而不同的时需要传递不同个数的参数
可变参数语法:数据类型…数组名public void add(int...nums){//nums可以理解为一个数组,可以传递多个参数 //方法体 }
注:
可变参数只能写在方法的参数列表中,不能单独定义
方法的参数列表中只能由一个可变参数
方法的参数列表中的可变参数,必须放在其它普通参数的后面
服务器及相关知识
软件体系结构
1.常用软件体系结构:B/S(详见java基础笔记,网络编程 )
2.Web资源
html:静态资源
JSP/Servlet:动态资源
静态资源和动态资源的区别:静态资源浏览器可以直接解析,动态资源需要先转换成html
Web资源的访问,通过在浏览器输入URL进行访问(协议://域名:端口/路径)3.web服务器
web服务器的作用是接受客户端的请求,给客户端做出响应
对于JavaWeb程序,需要有web服务器和JSP/Servlet容器,而当前应用最广的JavaWeb服务器为Tomcat
其它:JBoss,Resin,Weblogic…(支持JavaEE,EJB容器)Tomcat服务器
1.概述:由Apache提供,开源免费
启动服务器:startup.bat
关闭服务器:shutdown.bat
进入Tomcat主页:http://127.0.0.1:8080
配置端口号:apache-tomcat-7.0.92\conf\server.xml
tomcat目录结构:
/bin :存放各种平台下启动和停止tomcat的命令文件,如startup.bat,shutdown.bat
/conf:存放tomcat的各种配置文件
/lib:存放tomcat服务器所需的各种jar文件
/log:存放在tomcat的日志文件
/temp:tomcat运行时用于存放临时文件
/webapps:当发布web应用时,默认会将web应用的文件发布到此目录中2.创建Web应用
静态网站的创建:
1.在webapps目录下创建一个项目目录(文件夹)
2.在项目目录下创建一个html文件
访问http://127.0.0.1:8080/hello1/index.html
动态网站的创建:
1.在webapps目录下创建一个项目目录
2.在项目目录下创建如下内容
WB-INF目录//不能被客户端直接访问
WB-INF目录下创建web.xml文件(web文件中的内容,可以去其它项目中拿再修改)
lib文件夹
classes文件夹
创建静态或者动态页面3.用myeclipse创建JavaWeb应用
1.创建web项目,配置tomcat
2.访问webapps外部javaweb应用使用://第一种,在server.xml中的<host>元素中添加 <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Context path="itcast_hello" docBase="外部应用路径" /> </Host> //第二种,在本地conf/caalana/localhost目录下创建itcast_hello.xml文件中写 <Context docBase="外部应用路径" />
4.配置虚拟主机
在server.xml文件中添加并更改默认端口为80:<Host name="www.itcast.cn" appBase="webapps" unpackWARs="true" autoDeploy="true"> </Host>
更改host文件映射:www.itcast.cn 127.0.0.1
http协议
http:超文本传输协议
请求协议,响应协议参考:网络编程
请求协议的某些属性:
Referer->请求来自的页面(直接在地址栏输入的地址,则请求头中无此属性)//可以用于统计工作等
Content-Type->表单的数据类型,说明会使用url格式编码数据
Content-Length->请求体的长度
keyword->请求体内容,表单字段=表单输入的数据响应协议的某响应码:
200->请求成功
404->请求的资源没有找到
500->请求资源找到了,但是服务器内部出现了错误
302->重定向,表示服务器要求浏览器重新再发一个请求,过程如下:
304->比较if-Modified-Since的时间与文件真是的时间一样时,服务器会响应304,而且不会有响应正文,直接使用浏览器缓存的相同文件其它响应头:
告诉浏览器不要缓存的响应头
Expires:-1
Cache-Controt:no-cache
Pragma:no-cache
自动刷新响应头:
Refresh:3;url=url地址 //表示3秒之后自动跳转到相应的url地址html中指定响应头:
标签格式如下<meta http-equiv="" content=""> <meta http-equiv="Refresh" content="5;url=http://www.baidu.com"><!-- 写有此标签的html会在5秒后自动跳到百度网页 -->