最近重新设计一个程序,这个程序有一个功能是监视其他进程的内存使用情况,并且在满足一定条件的时候促发警告给用户。一般的条件是,内存超过某个阀值。可是如果希望这个条件可以复杂些,譬如超过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,可以看到输出结果的改变。
分享到:
相关推荐
1. **语言融合**:Jython结合了Python的易用性和Java的高性能,使得开发人员可以在两个世界之间自由切换。 2. **可移植性**:因为Jython运行在JVM上,所以它具有Java的跨平台特性,能在任何支持JVM的系统上运行。 3....
Jython 简单配置和使用 Jython 是一种完整的语言...Jython 是一种强大且灵活的语言,它可以将 Python 语言和 Java 语言结合起来,提供了一个巨大的资源库。它的代码简明性、方便性和易读性使其非常适合开发应用程序。
将JSON与Jython结合,可以创建强大的数据处理和网络应用。Jython提供了内置的json模块,该模块允许我们轻松地对JSON数据进行编码和解码。例如,我们可以使用`json.dumps()`将Python对象转换为JSON字符串,而`json....
本文主要介绍了 Java 实现调用 Jython 执行 Python 文件的方法,结合实例形式分析了 Java 调用 Jython 执行 Python 文件的常见操作技巧及相关问题解决方法。 Title 解释:Java 实现调用 Jython 执行 Python 文件的...
Jython是Python的一种实现,它完全兼容Python语法,同时又与Java平台紧密集成,使得开发者能够利用Python的简洁性和灵活性来编写Java应用程序。 Jython的核心特性包括: 1. **Python语法兼容性**:Jython遵循...
Jython的主要特点在于它将Python的简洁性和动态性与Java的强大性能和跨平台兼容性相结合。这使得开发者可以利用Java的库和框架,同时享受Python的易读性和快速开发优势。以下是Jython的一些核心概念和关键知识点: ...
综上所述,《科学数据分析使用Jython脚本与Java》这本书不仅介绍了科学数据处理的基本原理和技术,还深入探讨了如何通过Jython与Java相结合的方式提高数据分析效率和准确性。对于从事科学研究和数据分析工作的人员来...
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》不仅是一本全面介绍 Jython 技术的手册,也是 Python 和 Java 开发者深入探索两者结合可能性的重要参考书。无论是初学者还是有经验的...
此外,Jython 还支持 Python 和 Java 之间的无缝交互,使得开发者可以轻松地将 Java 类库与 Python 代码结合使用。 #### 三、Jython与Java对象映射 在 Jython 中,通过定义 Java 接口类,可以使 Jython 对象与 ...
1. 调用Java类:Jython可以直接导入Java的类和接口,如`import java.util.ArrayList`。 2. 创建Java对象:通过构造函数创建Java对象,如`list = ArrayList()`。 3. 调用Java方法:使用点号`.`来调用Java对象的方法,...
这种特性使得 Jython 成为在 Java 环境中进行混合编程的理想选择,尤其是在需要结合 Python 的易用性和 Java 的高性能时。 **Jython 安装步骤** 1. **下载 Jython Standalone**: 首先,你需要从 Maven 存储库...
总的来说,Jython-standalone-2.7.0.zip是一个强大的工具,它将Python的灵活性和Java的性能结合在一起,为开发者提供了一种跨平台的解决方案,特别是在需要混合使用Java和Python的场景下。通过解压这个压缩包并根据...
Jython结合了Python的强大功能与Java的广泛适用性,使得开发者能够利用Python的简洁语法和动态特性来开发跨平台的Java应用程序。Jython不仅保持了Python的易用性和灵活性,还充分利用了Java的强大生态系统,如标准库...
总之,Python(尤其是结合 `python-docx`)和 Jython(借助 Apache POI)都能有效地处理 Word 文档。选择哪种取决于项目需求,如是否需要利用 Java 生态系统或是否更倾向于 Python 的便利性。无论选择哪种,都能实现...
总的来说,Jython结合PySerial为Java环境下的串口控制提供了一种简洁而强大的解决方案。通过阅读`jython调用串口模块.doc`文档,你可以深入了解如何在Jython中有效地使用PySerial,以及如何解决可能出现的问题。对于...
Jython将Python语言的灵活性和简洁性与Java平台的强大功能相结合,使得开发者能够在Java环境中利用Python进行开发。 描述中的博文链接指向了ITEYE博客上的一篇文章,虽然具体内容没有给出,但可以推测这篇文章可能...
在IT行业中,XML(eXtensible Markup Language)是一种被广泛用于存储和传输数据的标记语言,它具有结构化和自解释的特点。...结合其对Java库的无缝集成,Jython成为了在Java生态系统中处理XML的理想选择。