<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tim[后端技术] &#187; scripting</title>
	<atom:link href="http://timyang.net/tag/scripting/feed/" rel="self" type="application/rss+xml" />
	<link>http://timyang.net</link>
	<description>Tim&#039;s blog, 关于后端架构、互联网技术、分布式、大型网络应用、NoSQL、Key Value等</description>
	<lastBuildDate>Mon, 02 Aug 2010 15:34:40 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>使用脚本引擎增加程序运行时动态执行能力(Java篇)</title>
		<link>http://timyang.net/java/java-scripting/</link>
		<comments>http://timyang.net/java/java-scripting/#comments</comments>
		<pubDate>Mon, 18 May 2009 11:30:33 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=174</guid>
		<description><![CDATA[对于非Web的后台服务程序，经常会碰到这样的需求：

动态改变程序运行时参数的能力。如Config.limitValue = 50
动态查看运行时候变量状态的能力，如 print(userMap.size())
执行代码的能力，如 userMap.clear()

对于需求1,非Web的程序没法像PHP/JSP那样直接改就生效，往往改了某个值，即使是一个配置参数都需要服务器重启一下。这对于很多线上服务来说成本太高。
对于上述2的需求，通常是编写庞大的后台管理程序来满足。或者是通过增加日志输出，但问题是某些变量只需要偶尔才看一下，因此很多系统中大部分日志开销基本上是无用的。
对于需求3,只有通过在IDE的debug模式下才能达到。
我觉得所有的后台程序都应该具备这样的能力，为了满足以上需求，于是考虑在所有程序里面嵌入一个小型的解释脚本引擎来实现。就像很多游戏程序嵌入Lua/Python来动态执行代码目的一样。
今天先说下Java中的实现方法，几年前用过BeanShell, 可以在Java VM里面解释执行多种类型脚本语言。但是发现已经多年不更新，原来是Java 6已经内建Scripting的支持，所以这些第三方的工具也都结束了历史使命。
Java 6自带的实际上是 Mozilla Rhino 的Java Script引擎，它使用JavaScript的语法，可以调用任意Java代码。更多介绍见Java Scripting Programmer&#8217;s Guide. Rhino除了import写法有点特殊外，基本语法和Java代码基本一致。如：
engine.eval("importClass(java.lang.System)");
engine.eval("println(System.currentTimeMillis())");
engine.eval("println('Source: http://timyang.net/java/java-scriptingjava-scripting/')");
于是做了一个简单的socket服务器，把发过来的文本直接执行，然后再把脚本执行产生的内容返回给发送方。目标达成。共40余行代码(包括注释和花括号)，无需任何第三方library。代码如下：
// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
// create a JavaScript engine
ScriptEngine engine = factory.getEngineByName("JavaScript");

while (true) {
    ServerSocket serverSocket = null;
    try {
        [...]]]></description>
			<content:encoded><![CDATA[<p>对于非Web的后台服务程序，经常会碰到这样的需求：</p>
<ol>
<li>动态改变程序运行时参数的能力。如Config.limitValue = 50</li>
<li>动态查看运行时候变量状态的能力，如 print(userMap.size())</li>
<li>执行代码的能力，如 userMap.clear()</li>
</ol>
<p>对于需求1,非Web的程序没法像PHP/JSP那样直接改就生效，往往改了某个值，即使是一个配置参数都需要服务器重启一下。这对于很多线上服务来说成本太高。</p>
<p>对于上述2的需求，通常是编写庞大的后台管理程序来满足。或者是通过增加日志输出，但问题是某些变量只需要偶尔才看一下，因此很多系统中大部分日志开销基本上是无用的。</p>
<p>对于需求3,只有通过在IDE的debug模式下才能达到。</p>
<p>我觉得所有的后台程序都应该具备这样的能力，为了满足以上需求，于是考虑在所有程序里面嵌入一个小型的解释脚本引擎来实现。就像很多游戏程序嵌入Lua/Python来动态执行代码目的一样。</p>
<p>今天先说下Java中的实现方法，几年前用过<a href="http://www.beanshell.org/" target="_blank">BeanShell</a>, 可以在Java VM里面解释执行多种类型脚本语言。但是发现已经多年不更新，原来是Java 6已经内建Scripting的支持，所以这些第三方的工具也都结束了历史使命。</p>
<p><span><span>Java 6自带的实际上是 <a href="http://www.mozilla.org/rhino">Mozilla Rhino</a> 的Java Script引擎，它使用JavaScript的语法，可以调用任意Java代码。</span></span>更多介绍见<a href="http://java.sun.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.html" target="_blank">Java Scripting Programmer&#8217;s Guide</a>. <span><span>Rhino除了import写法有点特殊外，基本语法和Java代码基本一致。如：</span></span></p>
<pre>engine.eval("importClass(java.lang.System)");
engine.eval("println(System.currentTimeMillis())");
engine.eval("println('Source: <a href="http://timyang.net/java/java-scriptingjava-scripting/">http://timyang.net/java/java-scriptingjava-scripting/</a>')");</pre>
<p>于是做了一个简单的socket服务器，把发过来的文本直接执行，然后再把脚本执行产生的内容返回给发送方。目标达成。共40余行代码(包括注释和花括号)，无需任何第三方library。代码如下：</p>
<pre>// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
// create a JavaScript engine
ScriptEngine engine = factory.getEngineByName("JavaScript");

while (true) {
    ServerSocket serverSocket = null;
    try {
        serverSocket = new ServerSocket(4444, 50, InetAddress.getByName("localhost"));
    } catch (IOException e) {
        System.err.println("Could not listen on port: 4444.");
        System.exit(1);
    }

    Socket clientSocket = null;
    try {
        clientSocket = serverSocket.accept();
    } catch (IOException e) {
        System.err.println("Accept failed.");
        System.exit(1);
    }

    PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),
            true);
    BufferedReader in = new BufferedReader(new InputStreamReader(
            clientSocket.getInputStream()));
    String inputLine, outputLine;

    while ((inputLine = in.readLine()) != null) {
        if ("quit".equals(inputLine))
                break;
        try {
            // evaluate JavaScript code from String
            out.println(engine.eval(inputLine));
        } catch (Exception e) {
            out.println("error:" + e.getMessage());
        }
    }
    out.close();
    in.close();
    clientSocket.close();
    serverSocket.close();
}</pre>
<p>启动程序之后只要 telnet localhost 4444 就可以执行任意代码并实时查看返回结果。</p>
<p>注意上面为了安全起见，只绑定了localhost地址，防止此功能被外部用户恶意使用。</p>
Similar Posts:<ul><li><a href="http://timyang.net/programming/c-erlang-java-performance/" rel="bookmark" title="November 11, 2009">C, Erlang, Java and Go Web Server performance test</a></li>

<li><a href="http://timyang.net/architecture/friendfeed-like-aggregator/" rel="bookmark" title="April 3, 2009">Ideas for creating a friendfeed like feed aggregator system</a></li>

<li><a href="http://timyang.net/linux/gearman-monitor/" rel="bookmark" title="August 26, 2009">利用Gearman来实现远程监控与管理</a></li>

<li><a href="http://timyang.net/lua/lua-coroutine-vs-java-wait-notify/" rel="bookmark" title="April 27, 2009">Lua coroutine vs Java wait/notify</a></li>

<li><a href="http://timyang.net/python/python-rest/" rel="bookmark" title="February 12, 2009">用Python实现CRUD功能REST服务</a></li>
</ul><!-- Similar Posts took 14.736 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/java/java-scripting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
