jdbc mysql遇到日期为0时即报异常。
这里需要在jdbc.url上多传一个参数 zeroDateTimeBehavior=convertToNull
用来告诉jdbc驱动,遇到date为0是设置为null。
jdbc mysql遇到日期为0时即报异常。
这里需要在jdbc.url上多传一个参数 zeroDateTimeBehavior=convertToNull
用来告诉jdbc驱动,遇到date为0是设置为null。
代码如下:
如果注释掉test2(),启动test2_1(),则test()消耗的时间大幅减少,不知原因。
import java.util.HashMap; import java.util.IdentityHashMap; import java.util.Map; public class Test4 { private static Map<Integer, Integer> map1 = new HashMap<Integer, Integer>(); private static Map<String, String> map2 = new HashMap<String, String>(); private static Map<String, String> map3 = new IdentityHashMap<String, String>(); private static String testKey = "helloworld"; private static long time; private static long time2; private static Integer a = 1500; public static void main(String[] args) { map3.put(testKey, testKey); for (int m = 1000; m < 1010; m++) { map1.put(m, m); map2.put("" + m, "" + m); map3.put("" + m, "" + m); } for (int mm = 0; mm < 100; mm++) { test1(); test2(); // test2_1(); } } public static void test1() { time = System.nanoTime(); for (int m = 0; m < 1000000000; m++) { map1.get(a); } time2 = System.nanoTime(); System.out.println("数字:" + (time2 - time)); } public static void test2() { time = System.nanoTime(); for (int m = 0; m < 1000000000; m++) { map2.get("hello"); } time2 = System.nanoTime(); System.out.println("字符:" + (time2 - time)); } public static void test2_1() { time = System.nanoTime(); for (int m = 0; m < 1000000000; m++) { map2.get("hello222222222222222222222222222222222222222222222222222222222222222222222222222222222222222"); } time2 = System.nanoTime(); System.out.println("字符:" + (time2 - time)); } public static void test3() { time = System.nanoTime(); for (int m = 0; m < 1000000000; m++) { map3.get(testKey); } time2 = System.nanoTime(); System.out.println("字符3:" + (time2 - time)); } }
今天启动jstatd时一直报下面的错误:
root@cvs jstatd]# jstatd -J-Djava.security.policy=/opt/joycube/jstatd/tools.policy Could not contact registry Connection refused to host: 192.168.17.12; nested exception is: java.net.ConnectException: Connection timed out java.rmi.ConnectException: Connection refused to host: 192.168.17.12; nested exception is: java.net.ConnectException: Connection timed out at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619) at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216) at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202) at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:341) at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source) at java.rmi.Naming.rebind(Naming.java:177) at sun.tools.jstatd.Jstatd.bind(Jstatd.java:57) at sun.tools.jstatd.Jstatd.bind(Jstatd.java:66) at sun.tools.jstatd.Jstatd.main(Jstatd.java:143) Caused by: java.net.ConnectException: Connection timed out at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:579) at java.net.Socket.connect(Socket.java:528) at java.net.Socket.<init>(Socket.java:425) at java.net.Socket.<init>(Socket.java:208) at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40) at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:147) at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613) ... 8 more
上面提示的ip很奇怪。这台机器的ip应该是10.234.10.12
运行hostname -i,显示为192.168.17.12
这是错误的IP,打开 /etc/hosts,发现里面配置了本机名cvs解析为192.158.17.12,这台机器以前换过ip,修改为10.234.10.12。
ok,jstatd可以正常运行了。
最近两天晚上以每分钟一次的频率进行热更新,测试这种压力程度是否会引起bug。
早上到公司一看服务器已经死掉了,提示outofmemory,看来应该是有一个内存举出的地方。
服务器直接挂掉,连dump内存都无法成功。
使用jprofiler观察内存中的对象时时变化。
jprofiler中发现classloader没有被释放掉?
google之:
http://zeroturnaround.com/rebellabs/rjc201/
http://frankkieviet.blogspot.com/2006/10/how-to-fix-dreaded-permgen-space.html
Classloader leaks I – How to find classloader leaks with Eclipse Memory Analyser (MAT)
得知:classloader中会引用所加载类中的静态属性,从而导致classloader内存泄露。
将内存dump出来后,使用clipse Memory Analyser (MAT),查看具体哪里泄露。
直接在eclipse 中查找memory analyser 出来好多个软件。
mat 的update site:http://download.eclipse.org/mat/1.3.1/update-site/
其它的memory analyser软件,有时间再去了解下。
Modifier.isAbstract(clazz.getModifiers())
以上方式用来判断是clazz是否为虚拟类。
app在tomcat中运行,默认使用的是WebappClassLoader。
InputStream inputStream =Thread.currentThread().getContextClassLoader().getResourceAsStream(“xls/” +
xlsName);
inputStream只要加载过一次后,就会被WebappClassLoader缓存起来,如果需要加载新的资源文件,需要修改为以下方式:
// 因为webappclassloader会缓存加载的资源,所以每次手动去打开文件 // InputStream inputStream = // GameInstance.gameClassLoader.getResourceAsStream("xls/" + // xlsName); URL xlsURL = GameInstance.gameClassLoader.getResource("xls/" + xlsName); URLConnection resConn = xlsURL.openConnection(); resConn.setUseCaches(false); InputStream inputStream = resConn.getInputStream();
改为logback后就发现freemark疯狂的输出log。
Logger.selectLoggerLibrary(Logger.LIBRARY_NONE);
最近几天一直在实现java的热更新。
本来以为使用classloader很容易搞定,结果走过了好几个坑。
1、classloader中的类不允许重复加载。
如果已经加载过的类,需要先判断 findLoadedClass(name)中是否存在,如果已经存在,不要再次加载。
2、classloader最初放在contextLister中,服务启动时,自动启动,结果发现异常无法补获,只好在action中手动加载来进行调试。
3、classloaderA和classloaderB加载相同的类,也会判断为不相同,因为是由不同的classloader加载的。
4、看起来需要在tomcat中使用自己的类进行加载才可以实现热更新。测试下。现在需要在tomcat设置自己的classloader,同时在加载新类时,不能再重新new classloader.
5、先测试下如何从jar中加载类。
晕死,因为我加一个判断字符串是使用的apache common中的stringutils,结果导致classloader直接死掉,还不抛出异常。看来,如果是context class loader,只使用java jdk中的类库。
6、同一个类在不同的classloader中加载,也无法相互赋值。
这里有两种解决方案:
1)在tomcat中使用custom class loader来加载所需要的所有类。
2)需要加载的类的父类和接口交给context class loader加载。这样就可以共同相同classloader加载的接口,通过不同的classloader来加载具体的实现类及子类。
现在终于使用第二种解决方案解决问题。对 classloader及类加载和热更新了解的更深入了。
同时需要测试下,多次defines类是否能行的通。
1、如果使用spring, 可以使用以下方式获得spring context中的所有的类:
public class GameReflect implements ApplicationContextAware { public ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } public void getAllClass(){ applicationContext.getBeansOfType(GameBaseAction.class); } }
2、除此之外,也可以从classloader中使用一种hack方式获得所有的类:
package cn.joylab.service; import java.lang.reflect.Field; import java.util.Vector; public class ClassLoaderTest extends GameBaseManagerTestCase { @org.junit.Test public void test1() { try { Field f = ClassLoader.class.getDeclaredField("classes"); f.setAccessible(true); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); Vector<Class> classes = (Vector<Class>) f.get(classLoader); for (Class c : classes) { System.out.println(c); } } catch (Exception e) { e.printStackTrace(); } } }
maven默认直接访问repo仓库,但国外的仓库太慢了。
这里可以在maven/conf/setting.xml中设置代理,设置一个连接国外网速比较快的代理:
<proxies>
<proxy>
<id>optional</id>
<active>true</active>
<protocol>http</protocol>
<username>proxyuser</username>
<password>proxypass</password>
<host>127.0.0.1</host>
<port>8087</port>
<nonProxyHosts>local.net|some.host.com|192.168.17.12|10.234.10.12</nonProxyHosts>
</proxy>
</proxies>
我这里是使用的goagent,所以就设置为本机的goagent为代理,速度果然提高了好多。
近期评论