我们可以在 applet 窗口或 Swing 窗口中运行 Java 程序吗?如何查看编译程序的输出?
4 回答
您可以使用Compiler API(在 Java 6 中可用)来编译源代码。
您可以 exec() 新进程(如果它有一个 main() 入口)点,或者使用类加载将其加载到您的 JVM 中。请注意,如果您参加后一门课程,您可能每次都必须实例化一个新的类加载器 - 请参阅此处了解更多详细信息。
您可能有安全问题。从小程序访问文件系统。因此,您最好只使用标准 Swing 应用程序(可能使用 Java Web Start 加载?)
Re. JavaCompiler API & Applet or Swing launched with JWS.
To compile source supplied in a text area, or by URL from the code-base would not require trust. OTOH the JavaCompiler
is only available if the code is running in the JVM of a JDK (it requires the tools.jar
to be on the run-time class-path). Applets and JWS based apps. are never run using a JDK and never have the tools.jar
available.
See also
- Example code for java compiler with a simple GUI code & discussion at OTN.
- STBC (based on that code).
- STBC Help. Goes into more detail on the
tools.jar
and the run-time class-path.
Example code
To avoid 'link rot', here is the code seen in that linked thread.
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.EventQueue;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.SwingWorker;
import javax.swing.border.EmptyBorder;
import java.util.ArrayList;
import java.net.URI;
import java.io.ByteArrayOutputStream;
import java.io.OutputStreamWriter;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler;
import javax.tools.SimpleJavaFileObject;
/** A simple Java compiler with a GUI. Java 1.6+.
@author Andrew Thompson
@version 2008-06-13
*/
public class GuiCompiler extends JPanel {
/** Instance of the compiler used for all compilations. */
JavaCompiler compiler;
/** The name of the public class. For 'HelloWorld.java',
this would be 'HelloWorld'. */
JTextField name;
/** The source code to be compiled. */
JTextArea sourceCode;
/** Errors and messages from the compiler. */
JTextArea output;
JButton compile;
static int pad = 5;
GuiCompiler() {
super( new BorderLayout(pad,pad) );
setBorder( new EmptyBorder(7,4,7,4) );
}
/** A worker to perform each compilation. Disables
the GUI input elements during the work. */
class SourceCompilation extends SwingWorker<String, Object> {
@Override
public String doInBackground() {
return compileCode();
}
@Override
protected void done() {
try {
enableComponents(true);
} catch (Exception ignore) {
}
}
}
/** Construct the GUI. */
public void initGui() {
JPanel input = new JPanel( new BorderLayout(pad,pad) );
Font outputFont = new Font("Monospaced",Font.PLAIN,12);
sourceCode = new JTextArea("Paste code here..", 15, 60);
sourceCode.setFont( outputFont );
input.add( new JScrollPane( sourceCode ),
BorderLayout.CENTER );
sourceCode.select(0,sourceCode.getText().length());
JPanel namePanel = new JPanel(new BorderLayout(pad,pad));
name = new JTextField(15);
name.setToolTipText("Name of the public class");
namePanel.add( name, BorderLayout.CENTER );
namePanel.add( new JLabel("Class name"), BorderLayout.WEST );
input.add( namePanel, BorderLayout.NORTH );
compile = new JButton( "Compile" );
compile.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent ae) {
(new SourceCompilation()).execute();
}
} );
input.add( compile, BorderLayout.SOUTH );
this.add( input, BorderLayout.CENTER );
output = new JTextArea("", 5, 40);
output.setFont( outputFont );
output.setEditable(false);
this.add( new JScrollPane( output ), BorderLayout.SOUTH );
}
/** Compile the code in the source input area. */
public String compileCode() {
output.setText( "Compiling.." );
enableComponents(false);
String compResult = null;
if (compiler==null) {
compiler = ToolProvider.getSystemJavaCompiler();
}
if ( compiler!=null ) {
String code = sourceCode.getText();
String sourceName = name.getText().trim();
if ( sourceName.toLowerCase().endsWith(".java") ) {
sourceName = sourceName.substring(
0,sourceName.length()-5 );
}
JavaSourceFromString javaString = new JavaSourceFromString(
sourceName,
code);
ArrayList<JavaSourceFromString> al =
new ArrayList<JavaSourceFromString>();
al.add( javaString );
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStreamWriter osw = new OutputStreamWriter( baos );
JavaCompiler.CompilationTask task = compiler.getTask(
osw,
null,
null,
null,
null,
al);
boolean success = task.call();
output.setText( baos.toString().replaceAll("\t", " ") );
compResult = "Compiled without errors: " + success;
output.append( compResult );
output.setCaretPosition(0);
} else {
output.setText( "No compilation possible - sorry!" );
JOptionPane.showMessageDialog(this,
"No compiler is available to this runtime!",
"Compiler not found",
JOptionPane.ERROR_MESSAGE
);
System.exit(-1);
}
return compResult;
}
/** Set the main GUI input components enabled
according to the enable flag. */
public void enableComponents(boolean enable) {
compile.setEnabled(enable);
name.setEnabled(enable);
sourceCode.setEnabled(enable);
}
public static void main(String[] args) throws Exception {
Runnable r = new Runnable() {
public void run() {
JFrame f = new JFrame("SSCCE text based compiler");
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
GuiCompiler compilerPane = new GuiCompiler();
compilerPane.initGui();
f.getContentPane().add(compilerPane);
f.pack();
f.setMinimumSize( f.getSize() );
f.setLocationRelativeTo(null);
f.setVisible(true);
}
};
EventQueue.invokeLater(r);
}
}
/**
* A file object used to represent source coming from a string.
* This example is from the JavaDocs for JavaCompiler.
*/
class JavaSourceFromString extends SimpleJavaFileObject {
/**
* The source code of this "file".
*/
final String code;
/**
* Constructs a new JavaSourceFromString.
* @param name the name of the compilation unit represented
by this file object
* @param code the source code for the compilation unit
represented by this file object
*/
JavaSourceFromString(String name, String code) {
super(URI.create(
"string:///" +
name.replace('.','/') +
Kind.SOURCE.extension),
Kind.SOURCE);
this.code = code;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return code;
}
}
使用Java Compiler API将源代码转换为字节码。之后使用动态类加载将编译后的字节码加载到 jvm 并启动它(以获取输出)。
此外,如果您想从 java 小程序内部执行此操作,则必须解决安全问题。
好吧,applet 是在后台运行的程序。为了编译一个 java 程序,出于安全原因,你需要访问IS NOT ALLOWED
一个 applet 的客户端本地磁盘(据我所知)。你想达到什么目的?我曾经尝试使用小程序访问 img 文件。