java.lang.NoClassDefFoundError: com/sun/mail/util/SharedByteArrayInputStream

java classloader体系结构
java classloader体系结构

最近碰到jar包冲突,抛出的异常:java.lang.NoClassDefFoundError: com/sun/mail/util/SharedByteArrayInputStream,导致发邮件发布出去。在线下无法重现,而线上确大部分情况都能重现。

在http://www.findjar.com搜了一下发现含有这个类的有mail-1.3.3.jar,而我工程里面使用的mail-1.4.5.jar。这样一来似乎把mail包的版本降低到1.3.3就行了。

but倔强的我不想降版本,所以不得不找出到底是哪里使用到了com.sum.mail.util.SharedByteArrayInputStream类,在网上百度了一番,发现j2ee.jar有嫌疑,我用的是j2ee-1.4.jar和mail-1.4.5.jar,把这个jar包使用jd反编译后看到了原因,j2ee-1.4.jar和mail-1.4.5.jar中都使用了javax.mail.internet.MimeMessage类,而j2ee-1.4.jar中的MimeMessage中import了com.sun.mail.util.SharedByteArrayInputStream类,mail-1.4.5.jar中的MimeMessage中import了javax.mail.util.SharedByteArrayInputStream类。在线下很可能mail-1.4.5.jar包中的MimeMessage类被优先load到jvm中,所以使用了javax.mail.util.SharedByteArrayInputStream类;而线上则很可能j2ee-1.4.jar中的MimeMessage类被优先load到jvm中,而com.sun.mail.util.SharedByteArrayInputStream类在整个web工程中确实不存在,所以出现了如题的异常。

这样一来解决的办法就是得升级j2ee.jar包,经查j2ee-5.jar使用MimeMessage类与mail-1.4.5.jar中的完全一样,都import的是javax.mail.util.SharedByteArrayInputStream类。这样把升级j2ee包到版本5就行了。

总结一下:j2ee-1.4.jar与mail-1.3.3jar匹配,j2ee-5.jar与mail-1.4.5.jar匹配即可避免jar包冲突。

mysql timeout setting using the Connector / J connection property ‘autoReconnect = true’ to avoid this problem.

最近发现应用隔段时间就不可用了,发现有如下的错误日志:

Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 45,012,127 milliseconds ago.  The last packet sent successfully to the server was 45,012,127 milliseconds ago. is longer than the server configured value of ‘wait_timeout’. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property ‘autoReconnect=true’ to avoid this problem.

经查,是因为默认的mysql的超时时间设置导致的:如果连接空闲超过8小时(即没有任何数据库操作),mysql会自动的断开与应用的链接,但可通过重启tomcat(或者其他web容器)的方式来解决。

以下是解决方案:

方案一

如果你的jdbc链接的url上没有autoReconnect=true参数的话,就添加类似下面的参数:

jdbc.url = jdbc:mysql ://ipaddress: 3306/database?autoReconnect=true&autoReconnectForPools=true

方案二

如果你使用了hibernate的话,还可以用下面的方式来配置:

<property name=”connection.autoReconnect”>true</property>
<property name=”connection.autoReconnectForPools”>true</property>
<property name=”connection.is-connection-validation-required”>true</property>

如果你使用的是c3p0连接池,可以这样配置:

<property name=”hibernate.c3p0.acquire_increment”>1</property>

<property name=”hibernate.c3p0.idle_test_period”>0</property>
<property name=”hibernate.c3p0.timeout”>0</property>
<property name=” hibernate. c3p0.validate”> true </property>

 方案三

最坏的方案:修改mysql的配置问加你my.cnf,wait_timeout 31536000就是一年,够长了:

[Mysqld]

wait_timeout = 31536000

interactive_timeout = 31536000

修改后,重启即可

或者参考这篇文章http://www.2cto.com/database/201312/261593.html动态修改超时时间。

值得注意的是,这种设置方法会对有的mysql上的所有数据库和所有客户端都有效,而往往不同的应用对超时时间的要求可能不尽相同,所以这种方法需要慎重使用。

Reference

http://www.databaseskill.com/2615216/

http://www.2cto.com/database/201312/261593.html

error the @annotation pointcut expression is only supported at Java 5 compliance level or above

碰到了这个error the @annotation pointcut expression is only supported at Java 5 compliance level or above报错,一看就知道是jar包冲突,在网上百度了半天,大部分的说法都是把org.aspectj:aspectjweaver:jar包升级到1.6以上,但是我尝试了还是不行。这种spring的jar冲突,基本只能考百度谷歌了。

后来把dependency tree打印出来,搜索aspectj后,发现我的工程里面除了aspectjweaver外,还有个aspectjtools,这两个的版本都偏低,于是把这两个包都升级到了1.7.3,重新mvn clean install eclipse:eclipse后果然成功。

我只想说这些jar包冲突真的好坑爹啊

Reference

Error when using AspectJ AOP with Java 7

eclipse的hot swap功能失效导致代码修改后必须重启web应用:Absent Line Number Information

很长时间一直被ecipse的hotSwap功能失效问题困扰,hotSwap是jvm的一个重要功能,它可以让你在正在运行的程序中,修改方法体内容,修改后的代码能在应用不重启的条件下生效。而且经常提示这样的错误:

Absent Line Number Information

The virtual machine was unable to remove all stack frames running old code from the call stack. The virtual machine is not supplying the debugger with valid data for those frames. Stepping into these obsolete frames may be hazardous to the target virtual machine

hotSwap这个功能能大大降低开发调试成本。可是原本eclipse中能正常工作的hotSwap功能居然不能用了。在网上找了很多的方案,基本都是在说Preferences –> Java –> Compiler –> Classfile Generation的几项要勾上。但是eclipse默认这几项就是勾上的。

经查阅n多资料后,发现其本质原因是虚拟机和调试器不配套。说明很可能有两套javac.exe(用来编译的)和jdb.exe(用来调试的)同时被使用了,而这两套还不是来自同一个jdk的。顺着这个思路,我查看了下我的环境变量,在cmd中敲”echo %PATH%”:

C:\Program Files (x86)\Common Files\NetSarang;D:\amd\AMD APP SDK\2.9\bin\x86_64;D:\amd\AMD APP SDK\2.9\bin\x86;C:\Program Files (x86)\AMD APP SDK\2.9\bin\x86_64;C:\Program Files (x86)\AMD APP SDK\2.9\bin\x86;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;D:\software\apache-maven-3.0.5\bin;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;%GOBIN%;C:\Program Files (x86)\Git\cmd;%GROOVY_HOME%\bin;C:\Program Files\TortoiseSVN\bin

jdk只配置了一个,看起来没什么异样。我尝试用everything软件在整个硬盘上搜索javac.exe,结果发现有两个javac.exe,一个在jdk下,还有一个在%SystemRoot%\system32下,而且这个system32目录下还有个java.exe。看来问题应该是在这里了,至于为什么system32下会有javac.exe,就不得而知了,把java相关的exe文件都删除后,再试了试果然hotSwap功能恢复了。

困扰我许久的问题终于被解开了。

Reference

http://stackoverflow.com/questions/957822/eclipse-unable-to-install-breakpoint-due-to-missing-line-number-attributes

小米1升级最新miui后很卡的请看这里

nnd,我的小米1是第一批买的,去年发现小米1的一些服务停止了,很不爽,只能升级到最新的miuiv4,后来又升级到miuiv5,近来几个月速度明显在下降,甚至到了很难用的地步,不知原因。

我一度在小米论坛上找破解方案。有人说小米已经抛弃米1了,不支持小米1了,所以把系统升级到最新的miuiv5后就自动慢了,还是回复出厂设置使用原来的android 2.3的miui吧;也有人说要想变得快点,就需要三清(清楚缓存,清楚用户数据,清楚所有数据)后,刷卡重装,感觉挺费劲的。

最近实在是不能忍受米1的慢了,正好米4出来了,看起来还不错,想入手玩玩,结果发现如今的手机没有当年那么好抢了,抢了几次都没有抢到。没办法,还是回来整米1吧。

话说红米手机的配置和米1差不多,为啥红米跑miuiv5一点问题都没有,我的米1这么卡呢,应该不是硬件配置的问题。所以我猜测是我曾经的多次系统升级,而软件不一定赶上了系统的版本升级,导致软件与系统有一定的调优方面的不兼容,另外,手机用了快3年了,卡和rom里的太多了,没有清理过,估计碎片也很多。所以这次我狠下心,不管费不费劲都要彻底的清空重装。

按照miui官网的教程这样刷机http://www.miui.com/shuaji-301.html:

  1. 下载相应的miui最新的稳定版安装包:http://www.miui.com/download.html
  2. 重命名安装包为 update.zip 拷贝至格式化后的SD卡的根目录
  3. 三清(清楚缓存,清楚用户数据,清楚所有数据),在关机状态下,同时按+音量键和关机键 进入recovery模式(此模式下:关机键为确认键,音量键为上下移动的按键),然后选择“简体中文”–>”清楚数据”–>分别清楚缓存,清楚用户数据,清楚所有数据,然后关机
  4. 把SD卡插入后,再使用步骤3中的方法进入recovery模式,选择“简体中文”后,选择“将update.zip安装至系统一”并确认。选择确认等待完成,然后重启即可

现在感觉我的米1速度快了不少,和当初刚买来是差不多的速度了。

eclipse中文乱码问题解决方案汇总

eclipse中文乱码都是因为字符编码与默认的编码不符合导致的,有很多的方法可以解决,不需要安装任何插件就可以搞定。针对不同的情况,需要使用不同的方案,下面就针对一些案例讲解如何解决乱码问题。解决乱码问题的主要思路是设置正确合适的编码,如果不知道目标文件原本的编码,可以进行一定的尝试,通常尝试下GBK和UTF-8这两个编码即可。

1. 设置单个文件的字符编码,解决单个文件的乱码问题

有时候不小心copy来的单个文件编码与你workspace的默认编码不一致,就导致了单个乱码。解决办法:在Pakcage Explorer或者Project Explorer视图里面,右键点击该文件–>选择“Properties”–>”Text file encoding”–>给”Other”项设置相应的编码。(需要注意的是,如果copy来的文件在eclipse中显示的是正常,但是编码与其他文件不一致,若你想统一编码,就需要在设置编码前,记得先把文件内容copy一下,然后设置好编码,再把copy的内容粘贴到编码修改后的文件中,这样会不乱码;一修改编码文件内容就会乱码),如下图:

eclipse设置单个文件的字符编码
eclipse设置单个文件的字符编码

2. 设置第三方jar包的字符编码,解决整个jar的乱码问题

第三方jar包的编码问题可能是最常见的问题,其解决方案与单个文件的比较类似,在Pakcage Explorer或者Project Explorer视图里面,右键第三方jar包–>选择“Properties”–>给”Encoding”项设置相应的编码,如下图:

在eclipse中给jar包设置字符编码
在eclipse中给jar包设置字符编码

3. 分别设置不同类型文件的字符编码

有时候为了统一所有工程的编码,可能需要提前设置好各类型文件的字符编码,比如:把所有的jar类都设置为GBK编码,把所有的xml设置为UTF-8编码等。这时候就需要有针对性的给不同类型的文件设置不同的编码。步骤是这样的:Windows–>Perferences–>General–>Content Types–>选择文件类型–>设置“Default encoding”项。如图下:

在eclipse中给指定类型的文件设置字符编码
在eclipse中给指定类型的文件设置字符编码

4. 设置整个workspace的文本文件的默认字符编码

往往workspace都有一个默认的字符编码,如果你的工程大部分或者全部是另一个编码,那么你可以重新设置一个默认的字符编码,后续新建工程就不需要再去设置编码了。步骤是这样的:Windows–>Perferences–>General–>Workspace–>Test file encoding–>给“Other:”设置相应的编码,如下图:

在eclipse中设置workspace的字符编码
在eclipse中设置workspace的字符编码

个人经验

其实一般开源的代码都是UTF-8编码的,我们平时开发的时候最好也都统一使用UTF-8,在开发初期直接把workspace的文本文件的编码设置为UTF-8,这比较省事。在开发过程中,如果发现添加进来的三方jar包编码不是UTF-8,那么可以针对这个jar设置其编码;若copy某个源码文件到工程中发现是乱码的,那么可以仅设置这一个文件的编码成正确的编码。

解决mysql命令行的字符编码问题

mysql命令行的字符编码问题是很常见的,也是比较麻烦的问题,但其实解决的方法比较简单,只需要知道哪些地方需要设置编码,并把这些编码设置成统一的就行了,比如:在使用mysql的命令行工具时,就需要设置命令行工具的字符编码与数据库的编码保持一致。

查看和设置数据库的字符编码

首先需要知道数据库的编码是怎么样的,可以使用下的命令,效果如下图:

show variables like ’character_set_%’;

查看数据库的编码
查看数据库的编码

除了charaacter_set_filesystem以外,其他的最好保持一致。可以看到我的数据库的字符编码设置都是utf8的。

这里的设置正确以后,就需要保证客户端的编码和数据库的编码一致,这样客户端才能正常显示数据库中的中文数据,数据库才能正确的识别客户端发来的带有中文的查询语句。

如果你的编码设置不一致,请使用类似下面的语句来设置编码:

set character_set_client=gb2312; // 客户端编码方式
set character_set_connection= gb2312; // 建立连接使用的编码
set character_set_database= gb2312; // 数据库的编码
set character_set_results= gb2312; // 结果集的编码
set character_set_server= gb2312; // 数据库服务器的编码

下面图文解释如何设置命令行工具的字符编码:

secureCRT的字符编码设置

在一个连接上右键,选择“属性”,如下图设置编码:

 

设置secureCRT的字符编码
设置secureCRT的字符编码

xshell的字符编码设置

如果你使用的是xshell作为你的命令行工具,那么你可以这样设置,在一个会话上,右键点击“属性”,然后按照如下设置你数据库对应的字符编码即可,我的数据库是用utf8,所以我设置了utf8:

 

xshell的字符编码设置
xshell的字符编码设置

Reference

WordPress搭建的博客访问变慢的解决方案

wordpress访问速度好慢
wordpress访问速度好慢

现在的wordpress博客突然变得访问速度及其慢,追求其原因是最近fonts.googleapis.com域名被众所周知的网络长城给墙了。这个域名在wordpress中有多处被使用了,要想知道有多少地方在用,可以这么干,使用你的空间管理工具(比如:cpanel等)把你的博客源码下载下来,然后在使用notepad++在所有源码文件中搜索fonts.googleapis.com,就会发现有多个文件有这个域名,不用想,直接全部替换fonts.useso.com就行了。

fonts.useso.com是360专门为了解救国内网站被墙问题而提供的cdn服务,速度还不错。如果还有一些其他被墙的资源,也许你可以在这里http://libs.useso.com/找到对应的国内cdn资源。

比如,在我的博客的主目录中搜索:

 

在wordpress源码中搜索fonts.googleapis.com
在wordpress源码中搜索fonts.googleapis.com

效果如下:

wordpress中有这么多的在wordpress源码中搜索fonts.googleapis.com
wordpress中有这么多的在wordpress源码中搜索fonts.googleapis.com

确实有多处使用了这个域名,所以都替换,然后重新上传源码即可。其中“twentytwelve”是我使用的主题目录。如果你使用的cpanel,那么可以效仿我的文件路径修改对应的文件也可以的。

 

远程桌面字体平滑设置

以前远程桌面链接的时候,看到字体很丑,很粗糙,字体不平滑,看着很不爽,今天才发现,原来是可以设置的,点“远程桌面连接”–>点击左下角“选项”–>选择“体验”–>选择适合自己的宽带(网速越好效果越好)–> 勾上“字体平滑”,ok,完成了。如下图:

远程桌面连接字体平滑设置
远程桌面连接字体平滑设置

 

当然如果你的网速很好,你可以把其他几个都勾选上,把显示里面的“颜色”选择最高的深度,那效果就跟没远程链接效果一样了。

很多人一直在忍受那样难看的字体,但不曾去解决这个问题,其实多看看多试试还是有办法的~

使用iPOJO时抛出异常java.lang.UnsupportedOperationException: Cannot add elements inside this collection

 

felix ipojo
felix ipojo

Felix iPOJO的功能很强大,配置也比较复杂,配置和实现代码之间有着千丝万缕的关联,完全脱离代码去配置iPOJO的component和instance势必不会达到自己想要的依赖注入效果,甚至很难查到问题的原因。尽管iPOJO的配置有iPOJO xml schemaiPOJO Annotation,但是仅仅按照schema和annotation来不一定能配置正确,还需要理解iPOJO配置背后的一些机制和原理,否则会出现一些奇怪的异常。见如下的代码和iPOJO annotation注解:

上面的代码乍一看没啥问题,但是其实这个component的timeoutConfigList属性是无法注入成功的,这和iPOJO的一些的依赖注入实现机制有关系,如果用以上的代码来配置instance,在启动这个component和instance所在的bundle时会抛出以下的异常堆栈:

我们可以看到属性timeoutConfigList是List集合类型,它上有@Requires的annotaion,又有对这个属性的@Bind和@Unbind方法。这种用法是不合适的。如果使用不当就会出现上面的异常。因为当在一个属性上注明了@Requires的annotaion时,就表示这个属性需要由ipojo来负责依赖注入,ipojo默认会为集合类型的属性创建一个ServiceCollection类的代理对象,也就是说timeoutConfigList属性在被替换成了ServiceCollection类的对象,调用这个对象里的所有修改方法都会抛出UnsupportedOperationException异常,因为这个属性已经交由ipojo的来维护了,对其进行修改、添加或者删除的话,可能会导致ipojo维护对象的混乱。而@Bind和@Unbind方法是在属性的代理对象创建后,当有适合的属性类型的对象满足注入条件时回调的方法,在以上的代码中有add和remove的操作自然会导致抛出上面的异常了。

解决办法

方法一: 同时使用@Requires注解以及@Bind和@Unbind方法时,保证@Bind和@Unbind方法中没有修改操作(可以执行非修改操作,比如contains、size、get等,详见ServiceCollection类的源码)

方法二: @Requires注解与@Bind、@Unbind方法不同时出现。其实@Bind、@Unbind方法基本包含了@Requires注解的功能,而且还可以对这个属性对象的注入进行aop操作,相比@Requires注解只是需要多写些判空和初始化的代码而已。

方法三:在示例代码的基础上,在@Requires的注解中添加proxy=false,这样示例代码就不会抛出异常了(这个时候这个属性在没有被bind过前,其值为null,所以需要做判空处理),比如下面的写法:

(如果没有使用annotation,而是component的配置也是用的xml方式,解决方案还是如上面的讲的三点相类似。)