JDK6中的源代码编译功能,网上给的示例一般都无法运行,会抛出ClassNotFoundException。
经过改良,主要原因是字节码输出的文件不对。现修改为输出到内存中。
/**
* 字符串变为Class
*
* @author wuyuhou
*
*/
public class StringToClass {
public static void main(String[] args) throws Exception {
Class clazz = loadClass("com.test.CalculatorTest",
"package com.test;"
+ "public class CalculatorTest {"
+ " public int multiply(int multiplicand, int multiplier) {"
+ " System.out.print(multiplicand + \" * \");"
+ " System.out.print(multiplier + \" = \");"
+ " return multiplicand * multiplier;"
+ " }"
+ "}", StringToClass.class.getClassLoader());
Object instance = clazz.newInstance();
Method m = clazz.getMethod("multiply", new Class[] {
int.class, int.class
});
Object[] o = new Object[] {
3, 2
};
System.out.println(m.invoke(instance, o));
}
public static Class loadClass(String className, String javaSource, ClassLoader loader) throws ClassNotFoundException {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
//源码Java对象
JavaFileObject sourceFileObject = new SimpleJavaFileObjectWrapper(className, Kind.SOURCE, javaSource, null);
//输出到内存中
ByteArrayOutputStream byteArrayOutput = new ByteArrayOutputStream();
//Class输出Java对象
JavaFileObject outputFileObject = new SimpleJavaFileObjectWrapper(className, Kind.CLASS, null, byteArrayOutput);
Iterable<JavaFileObject> files = Arrays.asList(sourceFileObject);
StandardJavaFileManager fileManager = new StandardJavaFileManagerWrapper(compiler.getStandardFileManager(null, null, null), outputFileObject);
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, null, null, files);
task.call();
//字节码数组
byte[] classBytes = byteArrayOutput.toByteArray();
return new SimpleClassLoader(loader).loadClass(classBytes);
}
private static class SimpleClassLoader extends ClassLoader {
public SimpleClassLoader(ClassLoader parent) {
super(parent);
}
public Class<?> loadClass(byte[] classBytes) throws ClassNotFoundException {
return defineClass(null, classBytes, 0, classBytes.length);
}
}
private static class SimpleJavaFileObjectWrapper extends SimpleJavaFileObject {
private String javaSource = null;
private ByteArrayOutputStream byteArrayOutput = null;
public SimpleJavaFileObjectWrapper(String className, Kind kind, String javaSource, ByteArrayOutputStream byteArrayOutput) {
super(URI.create("string:///" + className.replace('.', '/') + kind.extension), kind);
this.javaSource = javaSource;
this.byteArrayOutput = byteArrayOutput;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return javaSource;
}
@Override
public OutputStream openOutputStream() throws IOException {
return byteArrayOutput;
}
}
private static class StandardJavaFileManagerWrapper implements StandardJavaFileManager {
private StandardJavaFileManager defaultWrapper = null;
private JavaFileObject outputFileObject = null;
public StandardJavaFileManagerWrapper(StandardJavaFileManager defaultWrapper, JavaFileObject outputFileObject) {
this.defaultWrapper = defaultWrapper;
this.outputFileObject = outputFileObject;
}
public ClassLoader getClassLoader(Location location) {
return defaultWrapper.getClassLoader(location);
}
public Iterable<JavaFileObject> list(Location location, String packageName, Set<Kind> kinds, boolean recurse) throws IOException {
return defaultWrapper.list(location, packageName, kinds, recurse);
}
public String inferBinaryName(Location location, JavaFileObject file) {
return defaultWrapper.inferBinaryName(location, file);
}
public boolean handleOption(String current, Iterator<String> remaining) {
return defaultWrapper.handleOption(current, remaining);
}
public boolean hasLocation(Location location) {
return defaultWrapper.hasLocation(location);
}
public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) throws IOException {
return defaultWrapper.getJavaFileForInput(location, className, kind);
}
// 输出重新定位,否则就会报出ClassNotFoundException
public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
if (outputFileObject != null) {
return outputFileObject;
}
return defaultWrapper.getJavaFileForOutput(location, className, kind, sibling);
}
public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
return defaultWrapper.getFileForInput(location, packageName, relativeName);
}
public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
return defaultWrapper.getFileForOutput(location, packageName, relativeName, sibling);
}
public void flush() throws IOException {
defaultWrapper.flush();
}
public void close() throws IOException {
defaultWrapper.close();
}
public int isSupportedOption(String option) {
return defaultWrapper.isSupportedOption(option);
}
public boolean isSameFile(FileObject a, FileObject b) {
return defaultWrapper.isSameFile(a, b);
}
public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(Iterable<? extends File> files) {
return defaultWrapper.getJavaFileObjectsFromFiles(files);
}
public Iterable<? extends JavaFileObject> getJavaFileObjects(File... files) {
return defaultWrapper.getJavaFileObjects(files);
}
public Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(Iterable<String> names) {
return defaultWrapper.getJavaFileObjectsFromStrings(names);
}
public Iterable<? extends JavaFileObject> getJavaFileObjects(String... names) {
return defaultWrapper.getJavaFileObjects(names);
}
public void setLocation(Location location, Iterable<? extends File> path) throws IOException {
defaultWrapper.setLocation(location, path);
}
public Iterable<? extends File> getLocation(Location location) {
return defaultWrapper.getLocation(location);
}
}
}
分享到:
相关推荐
标题中的“jdk1.5 jdk1.6 反编译 工具”指的是用于对Java字节码进行反编译的软件,这类工具能够将Java的.class文件转换回可读的.java源代码形式,这对于理解和学习已有的Java类库或者进行逆向工程非常有帮助。...
在 JDK 1.8 版本中,开发者们有时需要查看已编译的`.class`文件的源代码,以便理解其内部工作原理或进行调试。这时,就需要用到反编译工具。反编译是从已编译的字节码文件(.class文件)还原出类似源代码的形式,...
在开发和维护Java应用程序时,理解并熟悉JDK源码对于开发者来说至关重要,特别是当需要对源代码进行调试、优化或扩展时。 首先,让我们深入了解一下JDK 1.7的关键特性: 1. **Diamond操作符**:在JDK 7中引入了...
我们要明白在jdk中,sun对rt.jar中的类编译时,去除了调试信息,这样在eclipse中就不能看到局部变量的值。这样的话,如果在debug的时候查看局部变量, 就必须自己编译相应的源码使之拥有调试信息。要达到这个目的,一是...
`src`目录则包含了JDK的所有源代码,这是理解JDK内部机制的关键。Java 8引入了许多新特性,如Lambda表达式、Stream API、默认方法和接口的私有方法等。在`src`目录下,我们可以找到这些新特性的实现细节,例如`java....
关于调试jdk源码显示源码变量值的rt.jar重编译包
本文将深入探讨"jdk反编译工具"这一主题,帮助你了解如何借助此类工具解决无法查看源代码的问题。 首先,让我们了解什么是反编译。反编译是将已编译的计算机程序(通常为字节码或机器码)转换回接近原始源代码的...
JavaCompiler 是 Java 中的一个编译器接口,提供了编译 Java 源代码的功能。在 Java SE6 中,JavaCompiler 接口是 javax.tools 包的一部分,提供了标准的方式来操作 Java 编译器。 使用 JavaCompiler 接口来编译 ...
解压该文件后,你将得到JDK 12的源代码。 在Ubuntu 18.04上编译JDK 12源码的步骤如下: 1. **安装依赖**:在编译源码之前,确保系统已经安装了必要的依赖库。打开终端并输入以下命令: ``` sudo apt-get update ...
Java开发是每一个程序员在职业生涯中必须要面对的重要环节,而深入理解JDK源代码更是提升编程技艺的关键步骤。JDK(Java Development Kit)是Java平台的标准版,包含了Java运行时环境、Java工具和Java基础类库。Java...
虽然反编译的代码可能不会完全与原始源代码相同,但对于理解逻辑和功能来说已经足够。这个工具对于排查问题、学习第三方库或者进行逆向工程来说,都是一个强大的辅助工具。 在实际开发中,了解JDK 1.8的新特性和...
Java反编译是Java开发中一个重要的辅助工具,它允许开发者查看和理解已编译的Class文件中的字节码,因为Java源代码在编译后会被转换为这种不可读的二进制格式。标题提到的"jdk反编译软件"正是针对这个需求而设计的,...
此外,源代码中的异常处理、同步机制、网络编程模型等也是重要的学习内容。 通过阅读和分析OpenJDK源代码,开发者不仅可以提高自己的编程技能,还能为开源社区贡献自己的力量,修复bug、提出改进方案,甚至参与新的...
2. **jdk.internal.vm.compiler**: 通常称为JIT(Just-In-Time)编译器,这部分源代码涉及到HotSpot虚拟机的动态编译技术。JDK12可能引入了新的编译策略或优化,以提高代码执行效率。 3. **jdk.charsets**: 这个...
Java JDK中的源代码是学习和理解Java编程语言及其运行机制的关键资源。这些源文件包含了Java开发工具集(Java Development Kit)的核心类库,涵盖了从基本的语法结构到高级特性的实现。下面我们将深入探讨这些源代码...
Java反编译是将已编译的Java字节码(.class文件)转换回源代码的过程,以便开发者能够查看和理解这些编译后的代码。JAD(Java Decompiler)是一款著名的开源Java反编译工具,它能帮助程序员分析、理解和重构已编译的...
虽然在JDK8之后,部分sun包已被移除或重命名,但在JDK7中,这部分源代码仍然是理解Java底层运行机制的关键。 sunw 目录: 这个目录在较旧的Sun Microsystems JDK中常见,主要用于提供特定于Solaris操作系统的类。在...
**Java JDK 1.6.0 源代码解析** Java Development Kit (JDK) 是Java编程语言的核心组件,它包含编译器、运行时环境、调试工具和其他实用工具。JDK 1.6.0 版本是历史上的一个里程碑,它在Java的发展历程中占有重要的...
在Java开发过程中,时常会遇到跨版本的问题,尤其是在旧版JDK环境中运行新版JDK编译的代码。这里我们讨论的焦点是“JDK1.5环境下编译的jar包在JDK1.4环境下运行”所遇到的问题,具体表现为“Unsupported major.minor...
标题“自己编译JDK”涉及的是一个技术过程,即如何从源代码层面构建Java Development Kit(JDK)。这个过程对于开发者来说具有重要的学习价值,因为它可以帮助深入理解JDK的工作原理,同时也为自定义功能或者优化JDK...