`

Java和Jython的结合

阅读更多

最近重新设计一个程序,这个程序有一个功能是监视其他进程的内存使用情况,并且在满足一定条件的时候促发警告给用户。一般的条件是,内存超过某个阀值。可是如果希望这个条件可以复杂些,譬如超过2G时并且持续增长2天,就告警;或者如果小于1G,并且在10天以内总体趋势是增长的,也告警。总之,这个条件可以支持很复杂的条件,并且需要动态修改(主模块不重启的情况下),所以我的选择是结合Java和Jython。其实Java上面可以选用JRuby, Scala, Groovy或者Javascript,选择Jython的理由有以下几点:

[1] 单位有一些项目已经使用了Python;

[2] Scala和Groovy会的人太少,太前卫了;

[3] Javascript很好,不过考虑到也许今后所有Java的程序扩展都会使用一种脚本语言,明显Javascript系统的交互能力太差。譬如链接数据库,处理文件啊

[4] Ruby是我太难割舍的,因为我喜欢Ruby,其实Ruby企业版已经比较稳定了,而且JRuby也有官方的支持。只不过,单位中已经有项目使用了Python,如果冒然的引入Ruby,势必会增加系统的复杂度。

[5] 即使有JPerl,JTcl,我也不会选用。原因很简单,我需要更好的模块化面向对象的脚本,面向对象不是银弹,可是大家都很熟悉面向对象了,而且实践证明面向对象鼓励大家写出好维护的代码(结合设计模式)。

[6] C++可以和Python集成(Boost.Python)(当然了,Lua更方便与C++集成,可是Lua会的人也太少)。

[7] 可以用Java写,然后用反射,可以做。不过我觉得脚本更好,省掉了编译的过程。(因为在现场,不能保证你的Unix上面装了JDK,只能保证一定有JRE)。

[8] 使用的是Java5,不是Java6,所以JSR233(好像是这个吧)不是直接可以用的。

 

因为这个项目是单位的项目,所以我把我做得Prestudy的小程序拿出来和大家共享一下解决方案。

 

我总喜欢用计算器这样的小例子来做PreStudy,呵呵。

 

首先设计一个计算器的接口ICalc(用Java写的), 如下:

 

package com.gmail.at.ankyhe.calc;

public interface ICalc {
	void pushData(int[] data);
	int getResult();
}
package com.gmail.at.ankyhe.calc;

public interface ICalc {
	void pushData(int[] data);
	int getResult();
}

 

 很显然,这个接口里面有两个函数。第一个函数是pushData,主模块调用这个函数把数据送给具体的Calc类(这个用Jython实现),然后通过getResult()得到结果,思路很简单。为了能够动态的发现更新的文件,我们把送数据给Calc并且从Calc得到结果的任务放到一个独立的线程里面,如下:

 

package com.gmail.at.ankyhe.calc;

import java.util.Arrays;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;

public class CalcTask implements Runnable {

	public CalcTask(ICalc aCalc) {
		calc = aCalc;
		rand = new Random((new Date()).getTime());
		arr = new int[3];
	}
	
	public ICalc setCalc(ICalc aCalc) {
  	ICalc tmp = calc; 
	  synchronized(this) {
  	  calc = aCalc;
	  }
  	return tmp;
	}

	public void run() {
		while (true) {
			for(int i = 0 ; i < arr.length; ++i) {
				arr[i] = rand.nextInt() % 50;
			}
			int rst = 0;
			synchronized (this) {
			  calc.pushData(arr);
			  rst = calc.getResult();
      }
			System.out.println(String.format("Input: %s --- Output: %d", 
					                        Arrays.toString(arr), rst));
			try {
				TimeUnit.SECONDS.sleep(50);
			} catch (InterruptedException ex) {
				ex.printStackTrace();
			}
		}
	}

	private ICalc calc;
	private Random rand;
	private int[] arr;
}

 

 然后主线程里面负责扫描Jython脚本和加载它,如下:

 

package com.gmail.at.ankyhe.calc;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.python.util.PythonInterpreter;


public class Main {
	
	public static ICalc getCalc() {
		Reader file = null;
		file = null;
		try {
			file = new FileReader(filename);
		} catch(FileNotFoundException ex) {
			System.out.println("Can't find the file.");
			System.exit(1);
		}
		try {
     	Reader in = new BufferedReader(file);
			PythonInterpreter interpreter = new PythonInterpreter();
			org.python.core.PyObject code = interpreter.compile(in);
			interpreter.exec(code);
			ICalc calc = (ICalc)interpreter.get("calc", ICalc.class);
			return calc;
		} finally {
			try {
				file.close();
			} catch(IOException ex) {
				System.out.print("Fail to close file");
				System.exit(1);
			}
		}
	}
	
	public static long getLastModified() {
	  long rst = 0L;
		File f = null;
		try {
			f = new File(filename);
			rst = f.lastModified();
		} catch(NullPointerException ex) {
			ex.printStackTrace();
			rst = -1; 
		}
		return rst;
	}

	public static void main(String[] args) throws InterruptedException {
	  // initialization
	  if (args.length == 0) {
	    System.out.println("Usage java -jar calc.jar <scriptfile>.");
	    System.exit(1);
	  }
	  
	  filename = args[0];
		ICalc calc = null;
		if (lastmodified == 0) {
			lastmodified = getLastModified();
			if (lastmodified == -1) {
        System.out
            .println(String.format("The file %s doesn't exit.", filename));
			}
			calc = getCalc();
		}
		if(calc == null) {
      System.out.print(String.format("The script file has no valid calc.",
          filename));
			System.exit(2);
		}
		
		// launch calc task
		CalcTask ct = new CalcTask(calc);
		ExecutorService es = Executors.newCachedThreadPool();
		es.execute(ct);
		es.shutdown();
		
		// main thread check the new script every 10 seconds
		while(true) {
			long modified = getLastModified();
			if (modified <= lastmodified) {
			  // do nothing	
			}
			else {
			  lastmodified = getLastModified(); 
			  ICalc newCalc = getCalc();
			  if (newCalc == null) {
			    System.out.print(String.format("The new script file has no valid calc.", 
			        filename));
			  }
			  else {
			    System.out.println("Ready to use new script file.");
			    ct.setCalc(newCalc); 
			    System.out.println("Use new script file.");
			  }
			}
			TimeUnit.SECONDS.sleep(10);
		}
	}
	
	public static String filename = null;
	public static long lastmodified = 0;

}
 

 

 核心的加载代码就是下面这一段:

 

PythonInterpreter interpreter = new PythonInterpreter();
org.python.core.PyObject code = interpreter.compile(in);
interpreter.exec(code);
ICalc calc = (ICalc)interpreter.get("calc", ICalc.class);

 

 注意,在Jython脚本中的calc一定是一个ICalc子类的对象,否则上面最后一句会抛出异常。Jython代码如下:

 

import sys
# add sys path
def addSysPath():
  sys.path.append("/Users/AnkyHe/proj/java/CalcPlugin/icalc.jar")

addSysPath()

from com.gmail.at.ankyhe.calc import ICalc

class MyCalc(ICalc):
  def __init__(self):
    pass
  def pushData(self, arr):
    self.arr = arr
  def getResult(self):
    return sum(self.arr)
    #return min(self.arr)

calc = MyCalc()

'''
if __name__ == '__main__':
  mycalc = MyCalc()
  arr = [1, -100, 20]
  mycalc.pushData(arr)
  if sum(arr) == mycalc.getResult():
    print('true')
  else:
    print('false')
    print(mycalc.getResult())
'''
 

sys.path.append是把接口ICalc的jar文件加入到Jython的使用环境中,这样才可以import ICalc。注意最后的if __name__ == '__main__', 这里体现了用Jython的一个优点,可以通过Jython做测试。因为这只是一个Presutdy,主要任务是验证一下这个流程,所以可能有一些错误处理没有写得很全面。源代码和可执行文件(我在Mac上编译运行通过了)如附件,执行的时候请用:

java -cp ./icalc.jar -jar calcplugin.jar script/mycalc.py

编译的时候使用把icalc.jar和jython.jar加入到classpath中。

然后你修改mycalc.py,可以看到输出结果的改变。

 

 

 

 

 

 

分享到:
评论

相关推荐

    Jython示例

    1. **语言融合**:Jython结合了Python的易用性和Java的高性能,使得开发人员可以在两个世界之间自由切换。 2. **可移植性**:因为Jython运行在JVM上,所以它具有Java的跨平台特性,能在任何支持JVM的系统上运行。 3....

    Jython简单配置和使用

    Jython 简单配置和使用 Jython 是一种完整的语言...Jython 是一种强大且灵活的语言,它可以将 Python 语言和 Java 语言结合起来,提供了一个巨大的资源库。它的代码简明性、方便性和易读性使其非常适合开发应用程序。

    json和jython

    将JSON与Jython结合,可以创建强大的数据处理和网络应用。Jython提供了内置的json模块,该模块允许我们轻松地对JSON数据进行编码和解码。例如,我们可以使用`json.dumps()`将Python对象转换为JSON字符串,而`json....

    Java实现调用jython执行python文件的方法

    本文主要介绍了 Java 实现调用 Jython 执行 Python 文件的方法,结合实例形式分析了 Java 调用 Jython 执行 Python 文件的常见操作技巧及相关问题解决方法。 Title 解释:Java 实现调用 Jython 执行 Python 文件的...

    New Riders - Jython for Java Programmers.rar_Riders_jython

    Jython是Python的一种实现,它完全兼容Python语法,同时又与Java平台紧密集成,使得开发者能够利用Python的简洁性和灵活性来编写Java应用程序。 Jython的核心特性包括: 1. **Python语法兼容性**:Jython遵循...

    Jython教程

    Jython的主要特点在于它将Python的简洁性和动态性与Java的强大性能和跨平台兼容性相结合。这使得开发者可以利用Java的库和框架,同时享受Python的易读性和快速开发优势。以下是Jython的一些核心概念和关键知识点: ...

    Scientific Data Analysis using Jython Scripting and Java

    综上所述,《科学数据分析使用Jython脚本与Java》这本书不仅介绍了科学数据处理的基本原理和技术,还深入探讨了如何通过Jython与Java相结合的方式提高数据分析效率和准确性。对于从事科学研究和数据分析工作的人员来...

    jython-standalone-2.7.1.jar

    Jython,这个名字源于Java和Python的结合,是一种Python的实现,它允许在Java平台上运行Python代码。标题中的"jython-standalone-2.7.1.jar"是一个独立的Jython版本,特别适用于Java环境,使得Java开发者能够无缝地...

    The Definitive Guide to Jython-Python for the Java Platform

    综上所述,《The Definitive Guide to Jython—Python for the Java Platform》不仅是一本全面介绍 Jython 技术的手册,也是 Python 和 Java 开发者深入探索两者结合可能性的重要参考书。无论是初学者还是有经验的...

    jython的用法及学习文档

    此外,Jython 还支持 Python 和 Java 之间的无缝交互,使得开发者可以轻松地将 Java 类库与 Python 代码结合使用。 #### 三、Jython与Java对象映射 在 Jython 中,通过定义 Java 接口类,可以使 Jython 对象与 ...

    jython简易教程

    1. 调用Java类:Jython可以直接导入Java的类和接口,如`import java.util.ArrayList`。 2. 创建Java对象:通过构造函数创建Java对象,如`list = ArrayList()`。 3. 调用Java方法:使用点号`.`来调用Java对象的方法,...

    Burpsuite环境Jython安装方法1

    这种特性使得 Jython 成为在 Java 环境中进行混合编程的理想选择,尤其是在需要结合 Python 的易用性和 Java 的高性能时。 **Jython 安装步骤** 1. **下载 Jython Standalone**: 首先,你需要从 Maven 存储库...

    jython-standalone-2.7.0.zip

    总的来说,Jython-standalone-2.7.0.zip是一个强大的工具,它将Python的灵活性和Java的性能结合在一起,为开发者提供了一种跨平台的解决方案,特别是在需要混合使用Java和Python的场景下。通过解压这个压缩包并根据...

    jython介绍1

    Jython结合了Python的强大功能与Java的广泛适用性,使得开发者能够利用Python的简洁语法和动态特性来开发跨平台的Java应用程序。Jython不仅保持了Python的易用性和灵活性,还充分利用了Java的强大生态系统,如标准库...

    python&jython;

    总之,Python(尤其是结合 `python-docx`)和 Jython(借助 Apache POI)都能有效地处理 Word 文档。选择哪种取决于项目需求,如是否需要利用 Java 生态系统或是否更倾向于 Python 的便利性。无论选择哪种,都能实现...

    jython串口控制方法介绍

    总的来说,Jython结合PySerial为Java环境下的串口控制提供了一种简洁而强大的解决方案。通过阅读`jython调用串口模块.doc`文档,你可以深入了解如何在Jython中有效地使用PySerial,以及如何解决可能出现的问题。对于...

    jython

    Jython将Python语言的灵活性和简洁性与Java平台的强大功能相结合,使得开发者能够在Java环境中利用Python进行开发。 描述中的博文链接指向了ITEYE博客上的一篇文章,虽然具体内容没有给出,但可以推测这篇文章可能...

    jython解析xml文件

    在IT行业中,XML(eXtensible Markup Language)是一种被广泛用于存储和传输数据的标记语言,它具有结构化和自解释的特点。...结合其对Java库的无缝集成,Jython成为了在Java生态系统中处理XML的理想选择。

Global site tag (gtag.js) - Google Analytics