作者存档: 朱坤乾 - 第15页

bat文件中使用mvn命令

mvn自身也是一个bat脚本。

因此,如果调用需要使用使用call进行调用

call mvn clean
call mvn

classloader java热更新

最近几天一直在实现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();
		}
	}

}

windows及linux脚本定位所在目录

windows下:

@echo off
cd /d %~dp0

将工作目录转至bat脚本所在的目录。

linux下:

currentDir=`dirname $0`

currentDir好为脚本所在的目录

如果有其它shell设置了环境变量则使用以下方式调用

. $shellPath/../tools/db_load_init.sh

maven设置代理

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为代理,速度果然提高了好多。

一篇介绍jsr用法的文章

一篇介绍jsr用法的文章:

https://today.java.net/pub/a/today/2008/04/10/source-code-analysis-using-java-6-compiler-apis.html#accessing-the-abstract-syntax-tree-the-compiler-tree-api

jsr可以将java source生成为一个TreePath,可以读取到该类中的所有信息。(除了备注 -.-!)。

可以了,现在转向eclipse adt看看能否获得带备注的ast。

64k大赛作品

请参考以下两个网址:

http://breakpoint.untergrund.net

http://www.scene.org

maven中导出所依赖的第三方包

mvn dependency:copy-dependencies -DoutputDirectory=lib   -DincludeScope=compile

将所有的使用的第三方包导出于lib目录下。

 

游戏业务逻辑拆分,mvn war包引用war包解决方案

游戏服务器端打为了一个war包。

这次做项目时,希望将游戏中的通用模块及通用业务模块拆分至一个公共项目中,然后每个游戏可以分别建立一个项目来引用公共项目,可以只需要写业务逻辑,而不再需要关心其它的方面。

2013.11.06 记:

其实前几天已经解决掉了最后一个遇到的问题:这里还要感谢run jetty插件的作者。

现在开始动手进行项目改造:

  1. 这里核心工程定义为xcore,定义依赖工程文件xcore-dep,提供用来进行编译所需要的类。
  2. 定义另一个工程xcore-game,该工程为实际发布的游戏包。这里放在这里是为了调试xcore工程。以后开发新游戏时,直接复制xcore-game包即可。
  3. 定义第三个工程xcore-moon,测试工程,用来测试更为复杂的功能。(这个等前两个工程完工后再完成).
  4. 先在xcore工程下尝试运行看看能否运行。mvn、jetty:run及jetty:run-war。全部运行通过。
  5. 在xcore中的pom.xml中添加以下代码,用来生成xcore中的包含类的jar包
    			<plugin>
    				<artifactId>maven-war-plugin</artifactId>
    				<version>2.4</version>
    				<configuration>
    					<attachClasses>true</attachClasses>
    				</configuration>
    			</plugin
  6. 在xcore-game工程中修改pom.xml
    			<plugin>
    				<groupId>org.apache.maven.plugins</groupId>
    				<artifactId>maven-war-plugin</artifactId>
    				<version>2.4</version>
    				<configuration>
    					<useCache>false</useCache>
    					<workDirectory>target/overlay-war-folder</workDirectory>
    					<overlays>
    						<overlay>
    						</overlay>
    						<overlay>
    							<groupId>cn.XXXXX</groupId>
    							<artifactId>xcore</artifactId>
    						</overlay>
    					</overlays>
    				</configuration>
    			</plugin>
  7. 运行xcore-game工程,遇到以下错误
    [ERROR] Nested in org.springframework.beans.factory.BeanCreationException: Error
     creating bean with name 'org.mybatis.spring.mapper.MapperScannerConfigurer#0' d
    efined in file [D:\workspace\xcore-game\target\tmp\webapp\WEB-INF\classes\applic
    ationContext-mybatis.xml]: Initialization of bean failed; nested exception is ja
    va.lang.NoSuchFieldError: NULL:
    java.lang.NoSuchFieldError: NULL
            at org.springframework.expression.TypedValue.<clinit>(TypedValue.java:31
    )

    打开生成的war包,发现里面spring-expression引入了两个不同的版本,修改pom.xml将旧版本排除掉。OK,顺利解决问题。

  8. 奇怪,前几天明明ren jetty插件可以正常运行,现在竟然跑不起来了。有空再查吧,先用jetty:run-war凑活。
  9. run jetty插件失效的原因找到了,在原工程里面mvn可以成功编译工程,现在新的工程中,依赖eclipse编译源码,mvn无法成功编译源码,无法编译的原因后续再查。(原因查找到了,原来我是copy过来的pom.xml,里面的包名没有修改导致的)

maven中直接添加jar包

<dependency>
<groupId>cn.kingsoft</groupId>
<artifactId>game-server</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/game-server-1.0.jar</systemPath>
</dependency>


Warning: Use of undefined constant XML - assumed 'XML' (this will throw an Error in a future version of PHP) in /opt/wordpress/wp-content/plugins/wp-syntaxhighlighter/wp-syntaxhighlighter.php on line 1048