如何动态设置方法体

kv_zhaokc 2009-07-16 08:48:07
现在有一个方法,他的方法体是不确定的。方法体需要从一个文件中读取代码。
如何实现?
...全文
144 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
daimojingdeyu 2009-07-17
  • 打赏
  • 举报
回复
编译可以不使用外部命令的调用,另外一种思路,引入jdk lib/tools.jar中的com.sun.tools.javac.Main类,
使用Main.compile(String[] filePathArray)对类进行编译,这样似乎更加完美一些。
huadis 2009-07-17
  • 打赏
  • 举报
回复
强,刚好我也遇到类似的情况
  • 打赏
  • 举报
回复
确实适合用脚本来做,技术探讨下不用脚本也未尝不可
非典型射手 2009-07-17
  • 打赏
  • 举报
回复
别闹了,这种动态执行的东西当然要用脚本来做了
紫炎圣骑 2009-07-17
  • 打赏
  • 举报
回复
什么工具?
ndcs_dhf2008 2009-07-17
  • 打赏
  • 举报
回复
有工具可用..
baetg 2009-07-17
  • 打赏
  • 举报
回复
用来修改的类文件:
package dynamicload;

public class Test
{
// 需要动态加载的方法
public void dyMethod()
{

}

public static void main(String[] args)
{
new Test().dyMethod();
}
}
--------------------------------------------------------------------------------
quqiujie»
2、控制修改类文件
package dynamicload;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

public class Control
{
private static final String lineSeparator = System
.getProperty("line.separator");

public static void main(String[] args)
{
// 1.从文件中读取方法体
String filePath = "E:\\\\eclipse\\\\JavaExam\\\\src\\\\dynamicload\\\\Test.java";
updateFile(filePath);

// 2、编译java文件
// String cmd1 = "cd E:\\\\eclipse\\\\JavaExam\\\\src\\\\dynamicload";
String cmd2 = "javac -d E:\\\\eclipse\\\\JavaExam\\\\bin E:\\\\eclipse\\\\JavaExam\\\\src\\\\dynamicload\\\\Test.java";
try
{
// Runtime.getRuntime().exec(cmd1);
Runtime.getRuntime().exec(cmd2);
System.out.println("编译java文件成功");
}
catch (IOException e)
{
// 捕获异常:异常处理
e.printStackTrace();
}

// 休息一会,编译java,太快的话还没有编译好,就无法执行其方法了
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
// 捕获异常:异常处理
e.printStackTrace();
}

// 3、动态加载类文件
DynamicLoadClass("E:\\\\eclipse\\\\JavaExam\\\\bin");
}

/**
* @函数功能:[]
* @param string
*/
private static void DynamicLoadClass(String classPath)
{
try
{
URL[] urls = null;
// Convert the file object to a URL
File dir = new File(classPath);
URL url = dir.toURL(); // file:/c:/almanac1.4/examples/
urls = new URL[]
{ url };

// Create a new class loader with the directory
ClassLoader cl = new URLClassLoader(urls);

// Load in the class
Class loadClass = cl.loadClass("dynamicload.Test");

// Create a new instance of the new class
// Class plugin = Class.forName(plugInfo.getPlugClass());
Object pluginInstance = loadClass.newInstance();

// 方法调用
Method method = loadClass.getMethod("dyMethod", null);
method.invoke(pluginInstance, null);
}
catch (Exception e)
{
// 捕获异常:异常处理
e.printStackTrace();
}
}
紫炎圣骑 2009-07-17
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 daimojingdeyu 的回复:]
编译可以不使用外部命令的调用,另外一种思路,引入jdk lib/tools.jar中的com.sun.tools.javac.Main类,
使用Main.compile(String[] filePathArray)对类进行编译,这样似乎更加完美一些。
[/Quote]

这个如何使用?能否举个例子。
filePathArray 这个参数如何传值?
如何制定java文件路径和class文件路径?
紫炎圣骑 2009-07-17
  • 打赏
  • 举报
回复
3、方法体文件,简单举个例子,内容如下:

int i = 10000;
System.out.println(i);

将其保存为methodbody.txt文件。

紫炎圣骑 2009-07-17
  • 打赏
  • 举报
回复
/**
* @函数功能:[更新文件,原理是:将旧有的文件一行一行读出来,
* 修改后再一行一行写到新文件中,读完后将新文件替换旧文件]
* @param filePath
*/
private static void updateFile(String filePath)
{
File javafile = new File(filePath);
try
{
String newFileName = javafile.getAbsolutePath() + ".new";
String writedcontent = "";
FileOutputStream os = new FileOutputStream(newFileName);
FileReader filereader = new FileReader(javafile);
LineNumberReader lineReader = new LineNumberReader(filereader);
String line = lineReader.readLine();
while (null != line)
{
// 如果是需要更新的方法
if (line.trim().startsWith("public void dyMethod()"))
{
writedcontent = line + lineSeparator;
os.write(writedcontent.getBytes());
line = lineReader.readLine();

if (line.trim().startsWith("{"))
{
writedcontent = getMethodBody();
os.write(writedcontent.getBytes());
line = lineReader.readLine();
continue;
}
}

writedcontent = line + lineSeparator;
os.write(writedcontent.getBytes());

line = lineReader.readLine();
}

os.flush();
os.close();
os = null;
filereader.close();

javafile.delete();

File newFile = new File(newFileName);
newFile.renameTo(javafile);
}
catch (Exception e)
{
// TODO: handle exception
e.printStackTrace();
}

}

/**
* @函数功能:[]
* @return
*/
private static String getMethodBody()
{
StringBuffer sb = new StringBuffer();
try
{
FileReader filereader = new FileReader(
"E:\\eclipse\\JavaExam\\methodbody.txt");
LineNumberReader lineReader = new LineNumberReader(filereader);
String line = "";
sb.append(" {").append(lineSeparator);

while (null != (line = lineReader.readLine()))
{
sb.append(line).append(lineSeparator);
}

filereader.close();
}
catch (FileNotFoundException e)
{
// 捕获异常:异常处理
e.printStackTrace();
}
catch (IOException e)
{
// 捕获异常:异常处理
e.printStackTrace();
}
return sb.toString();
}

}
KK3K2005 2009-07-17
  • 打赏
  • 举报
回复
就是插件的实现

定义一个方法体的接口
然后调用实现接口的对象
实现接口的对象class文件可以复制到类层次目录下
  • 打赏
  • 举报
回复
这个帖子很有意思,自己写了个。文件的路径被写死了,因为实在
不知道该如何定位文件,运行的时候把这个文件放到D盘根目录
在dos下编译
javac -d . *.java
java com.saturday.asm.MyClassEditor
此程序在xp jdk1.6下调试通过

package com.saturday.asm;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Method;

public class MyClassEditor {
public static void main(String[] args){
File f=new File("d:/MyClass.java");
BufferedWriter writer;

try{
if(!f.exists()) f.createNewFile();
writer=new BufferedWriter(new FileWriter(f));

//重写类方法
writer.write("package com.saturday.asm;\n");
writer.write("public class MyClass extends MyClassEditor{\n");
writer.write("public void test(){\n");
writer.write("System.out.println(\"hello world! random="+Math.random()+"\");\n");
writer.write("}\n");
writer.write("}\n");
writer.close();

//编译类
Runtime run=Runtime.getRuntime();
run.exec("javac MyClass.java");

//执行类
Class cls;
int i=1;
//扫描直至类被编译完毕,可能有更好的方法来实现
//我对多线程什么的不懂只会这样做
while(true){
try{
cls=Class.forName("com.saturday.asm.MyClass");
break;
}catch (Exception e) {
System.out.println("第"+(i++)+"次加载失败!");
}
//休眠时间的长短视机器性能而定,我的机器慢定的长一些
Thread.sleep(200);
}

Object clsIns=cls.newInstance();
Method method=cls.getMethod("test",null);
method.invoke(clsIns,null);

}catch(Exception ex){
ex.printStackTrace();
}
}

public void test(){

}
}
tongliaozhang 2009-07-16
  • 打赏
  • 举报
回复
个人觉的没办法实现 楼上的方法 怎么在程序运行过程中编译并且加载java文件啊 估计得调用JVM的方法来做了 有点深~~
紫炎圣骑 2009-07-16
  • 打赏
  • 举报
回复
这个实现比较麻烦:
1、读入方法体;
2、重新编译java文件成class;
3、加载class文件

kv_zhaokc 2009-07-16
  • 打赏
  • 举报
回复
因为方法体不是由我确定的,而且别人只将方法体放在一个文件中。
紫炎圣骑 2009-07-16
  • 打赏
  • 举报
回复
这个应用好奇怪,为什么要从文件中读取?

把方法写好,根据不同的场景,选择不同的方法不好么?

请问楼主的应用场景是什么?
gannbatte 2009-07-16
  • 打赏
  • 举报
回复
很高深,留名。。。。
  • 打赏
  • 举报
回复
mark
紫炎圣骑 2009-07-16
  • 打赏
  • 举报
回复
2、控制修改类文件
package dynamicload;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

public class Control
{
private static final String lineSeparator = System
.getProperty("line.separator");

public static void main(String[] args)
{
// 1.从文件中读取方法体
String filePath = "E:\\eclipse\\JavaExam\\src\\dynamicload\\Test.java";
updateFile(filePath);

// 2、编译java文件
// String cmd1 = "cd E:\\eclipse\\JavaExam\\src\\dynamicload";
String cmd2 = "javac -d E:\\eclipse\\JavaExam\\bin E:\\eclipse\\JavaExam\\src\\dynamicload\\Test.java";
try
{
// Runtime.getRuntime().exec(cmd1);
Runtime.getRuntime().exec(cmd2);
System.out.println("编译java文件成功");
}
catch (IOException e)
{
// 捕获异常:异常处理
e.printStackTrace();
}

// 休息一会,编译java,太快的话还没有编译好,就无法执行其方法了
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
// 捕获异常:异常处理
e.printStackTrace();
}

// 3、动态加载类文件
DynamicLoadClass("E:\\eclipse\\JavaExam\\bin");
}

/**
* @函数功能:[]
* @param string
*/
private static void DynamicLoadClass(String classPath)
{
try
{
URL[] urls = null;
// Convert the file object to a URL
File dir = new File(classPath);
URL url = dir.toURL(); // file:/c:/almanac1.4/examples/
urls = new URL[]
{ url };

// Create a new class loader with the directory
ClassLoader cl = new URLClassLoader(urls);

// Load in the class
Class loadClass = cl.loadClass("dynamicload.Test");

// Create a new instance of the new class
// Class plugin = Class.forName(plugInfo.getPlugClass());
Object pluginInstance = loadClass.newInstance();

// 方法调用
Method method = loadClass.getMethod("dyMethod", null);
method.invoke(pluginInstance, null);
}
catch (Exception e)
{
// 捕获异常:异常处理
e.printStackTrace();
}
}
紫炎圣骑 2009-07-16
  • 打赏
  • 举报
回复
1.用来修改的类文件:
package dynamicload;

public class Test
{
// 需要动态加载的方法
public void dyMethod()
{

}

public static void main(String[] args)
{
new Test().dyMethod();
}
}
加载更多回复(8)

62,621

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧