- 浏览: 1317466 次
- 性别:
- 来自: 广州
文章分类
- 全部博客 (351)
- Java General (37)
- .net General (2)
- Linux Toy (55)
- Oracle (81)
- Mysql (11)
- Programer Career (12)
- Oh, my living ! (2)
- Shell Script (8)
- Web Service (0)
- Linux Server (22)
- Php/Python/Perl (3P) (2)
- Javascript General (5)
- Saleforce Apex Dev (2)
- Web General (5)
- Xen & VM tech. (17)
- PSP (13)
- OpenSolaris (34)
- php (1)
- RAI/flex/action script (16)
- asterisk/CTI (7)
- 交互设计 (6)
- English (3)
- Lucene (1)
最新评论
-
GuolinLee:
markmark
JVM调优总结 -Xms -Xmx -Xmn -Xss -
di1984HIT:
写的太好啊。
JVM调优总结 -Xms -Xmx -Xmn -Xss -
javajdbc:
javajdbc 写道
JVM调优总结 -Xms -Xmx -Xmn -Xss -
javajdbc:
...
JVM调优总结 -Xms -Xmx -Xmn -Xss -
alvin198761:
非常感谢,国外的被封杀了,你这里还有一份
How to Convert An Image-Based Guest To An LVM-Based Guest
The javax.tools package, added to Java SE 6 as a standard API for compiling Java source, lets you add dynamic capabilities to extend static applications. This article provides an overview of the major classes in the package and demonstrates how to use them to create a façade for compiling Java source from Java Strings, StringBuffers, or other CharSequences, instead of files. It then uses this façade to build an interactive plotting application that lets the user express a numeric function y = f(x) using any valid numeric Java expression. Finally, it discusses the possible security risks associated with dynamic source compilation and ways to deal with those risks.
The idea of extending applications via compiling and loading Java extensions isn't new, and several existing frameworks support this capability. JavaServer Pages (JSP) technology in Java Platform, Enterprise Edition (Java EE) is a widely known example of a dynamic framework that generates and compiles Java classes. The JSP translator transforms .jsp files into Java servlets, using intermediate source-code files that the JSP engine then compiles and loads into the Java EE servlet container. The compilation is often performed by directly invoking the javac compiler, which requires an installed Java Development Kit (JDK) or by calling com.sun.tools.javac.Main, which can be found in Sun's tools.jar. Sun's licensing allows tools.jar to be redistributed with the full Java Runtime Environment (JRE). Other ways to implement such dynamic capabilities include using an existing dynamic scripting language (such as JavaScript or Groovy) that integrates with the application's implementation language (see Resources) or writing a domain-specific language and associated language interpreter or compiler.
Other frameworks (such as NetBeans and Eclipse) allow extensions that developers code directly in the Java language, but such systems require external static compilation and source and binary management of the Java code and its artifacts. Apache Commons JCI provides a mechanism to compile and load Java classes into a running application. Janino and Javassist also provide similar dynamic capabilities, although Janino is limited to pre-Java 1.4 language constructs, and Javassist works not at the source-code level but at a Java class abstraction level. (See Resources for links to these projects.) However, because Java developers are already adept at writing in the Java language, a system that lets you simply generate Java source code on the fly and then compile and load it promises the shortest learning curve and the most flexibility.
Using javax.tools has the following advantages:
- It is an approved extension of Java SE, which means it's a standard API developed through the Java Community Process (as JSR 199). The com.sun.tools.javac.Main API is specifically not part of the documented Java platform API and isn't necessarily available in other vendors' JDKs or guaranteed to have the same API in future releases of the Sun JDK.
- You use what you know: Java source, not bytecodes. You can create correct Java classes by generating valid Java source without needing to worry about learning the more intricate rules of valid bytecode or a new object model of classes, methods, statements, and expressions.
- It simplifies, and standardizes on, one supported mechanism for code generation and loading without limiting you to file-based source.
- It's portable across different vendor implementations of the JDK Version 6 and above, both current and future.
- It uses a validated version of the Java compiler.
- Unlike interpreter-based systems, your loaded classes benefit from all the JRE's runtime optimizations.
|
Java compilation: Concepts and implementation
To understand the javax.tools package, it's helpful to review Java compilation concepts and how the package implements them. The javax.tools package provides abstractions for all of these concepts in a general way that lets you provide the source code from alternate source objects rather than requiring the source to be located in the file system.
Compiling Java source requires the following components:
- A classpath, from which the compiler can resolve library classes. The compiler classpath is typically composed of an ordered list of file system directories and archive files (JAR or ZIP files) that contain previously compiled .class files. The classpath is implemented by a JavaFileManager that manages multiple source and class JavaFileObject instances and the ClassLoader passed to the JavaFileManager constructor. A JavaFileObject is a FileObject, specialized with one of the one of the JavaFileObject.Kind enumerated types useful to the compiler:
- SOURCE
- CLASS
- HTML
- OTHER
- javac options, which are passed as an Iterable<String>
- Source files — one or more .java source files to compile. JavaFileManager provides an abstract file system that maps source and output file names to JavaFileObject instances. (Here, file means an association between a unique name and a sequence of bytes. The client doesn't need to use an actual file system.) In this article's example, a JavaFileManager manages mappings between class names and the CharSequence instances containing the Java source to compile. A JavaFileManager.Location contains a file name and a flag that indicates if the location is a source or an output location. ForwardingJavaFileManager implements the Chain of Responsibility pattern (see Resources), allowing file managers to be chained together, just as a classpath and source paths chain JARs and directories together. If a Java class isn't found in the chain's first element, the lookup is delegated to the rest of the items in the chain.
- Output directories, where the compiler writes generated .class files. Acting as a collection of output class files, the JavaFileManager also stores JavaFileObject instances representing compiled CLASS files.
- The compiler itself. The JavaCompiler creates JavaCompiler.CompilationTask objects that compile source from JavaFileObject SOURCE objects in the JavaFileManager, creating new output JavaFileObject CLASS files and Diagnostics (warnings and errors). The static ToolProvider.getSystemJavaCompiler() method returns the compiler instance.
- Compiler warnings and errors, which are implemented with Diagnostic and DiagnosticListener. A Diagnostic is a single warning or compile error emitted by the compiler. A Diagnostic specifies:
- Kind (ERROR, WARNING, MANDATORY_WARNING, NOTE, or OTHER)
- A source location (including a line and column number)
- A message
Figure 1 maps the javac concepts to their implementations in javax.tools:
Figure 1. How javac concepts map to javax.tools interfaces
With these concepts in mind, you'll now see how to implement a façade for compiling CharSequences.
|
Compiling Java source in CharSequence instances
In this section, I'll construct a façade for javax.tools.JavaCompiler. The javaxtools.compiler.CharSequenceCompiler class (see Download) can compile Java source stored in arbitrary java.lang.CharSequence objects (such as String, StringBuffer, and StringBuilder), returning a Class. CharSequenceCompiler has the following API:
- public CharSequenceCompiler(ClassLoader loader, Iterable<String> options) : This constructor accepts a ClassLoader that is passed to the Java compiler, allowing it to resolve dependent classes. The Iterable options allow the client to pass additional compiler options that correspond to the javac options.
- public Map<String, Class<T>> compile(Map<String, CharSequence> classes, final DiagnosticCollector<JavaFileObject> diagnostics) throws CharSequenceCompilerException, ClassCastException : This is the general compilation method that supports compiling multiple sources together. Note that the Java compiler must handle cyclic graphs of classes, such as A.java depending on B.java, B.java depending on C.java, and C.java depending on A.java. The first argument to this method is a Map whose keys are fully qualified class names and whose corresponding values are CharSequences containing the source for that class. For example:
- "mypackage.A" ⇒ "package mypackage; public class A { ... }";
- "mypackage.B" ⇒ "package mypackage; class B extends A implements C { ... }";
- "mypackage.C" ⇒ "package mypackage; interface C { ... }"
- public ClassLoader getClassLoader() : This method returns the class loader that the compiler assembles when generating .class files, so that you can load other classes or resources from it.
- public Class<T> loadClass(final String qualifiedClassName) throws ClassNotFoundException : Because the compile() method can define multiple classes (including public nested classes), this method allows these auxiliary classes to be loaded.
To support this CharSequenceCompiler API, I implement the javax.tools interfaces with the classes JavaFileObjectImpl (for storing the CharSequence sources and CLASS output emitted by the compiler) and JavaFileManagerImpl (which maps names to JavaFileObjectImpl instances to manage both the source sequences and the bytecode emitted from the compiler).
JavaFileObjectImpl, shown in Listing 1, implements JavaFileObject and holds a CharSequence source (for SOURCE) or a ByteArrayOutputStream byteCode (for CLASS files). The key method is CharSequence getCharContent(final boolean ignoreEncodingErrors), through which the compiler obtains the source text. See Download for the complete source for all the code examples.
Listing 1. JavaFileObjectImpl (partial source listing)
final class JavaFileObjectImpl extends SimpleJavaFileObject { private final CharSequence source; JavaFileObjectImpl(final String baseName, final CharSequence source) { super(CharSequenceCompiler.toURI(baseName + ".java"), Kind.SOURCE); this.source = source; } @Override public CharSequence getCharContent(final boolean ignoreEncodingErrors) throws UnsupportedOperationException { if (source == null) throw new UnsupportedOperationException("getCharContent()"); return source; } } |
FileManagerImpl (see Listing 2) extends ForwardingJavaFileManager to map qualified class names to JavaFileObjectImpl instances:
Listing 2. FileManagerImpl (partial source listing)
final class FileManagerImpl extends ForwardingJavaFileManager<JavaFileManager> { private final ClassLoaderImpl classLoader; private final Map<URI, JavaFileObject> fileObjects = new HashMap<URI, JavaFileObject>(); public FileManagerImpl(JavaFileManager fileManager, ClassLoaderImpl classLoader) { super(fileManager); this.classLoader = classLoader; } @Override public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException { FileObject o = fileObjects.get(uri(location, packageName, relativeName)); if (o != null) return o; return super.getFileForInput(location, packageName, relativeName); } public void putFileForInput(StandardLocation location, String packageName, String relativeName, JavaFileObject file) { fileObjects.put(uri(location, packageName, relativeName), file); } } |
With these support classes, I can now define the CharSequenceCompiler. It's constructed with a runtime ClassLoader and compiler options. It uses ToolProvider.getSystemJavaCompiler() to get the JavaCompiler instance, then instantiates a JavaFileManagerImpl that forwards to the compiler's standard file manager.
The compile() method iterates over the input map, constructing a JavaFileObjectImpl from each name/CharSequence and adding it to the JavaFileManager so the JavaCompiler finds them when calling the file manager's getFileForInput() method. The compile() method then creates a JavaCompiler.Task instance and runs it. Failures are thrown as a CharSequenceCompilerException. Then, for each source passed to the compile() method, the resulting Class is loaded and placed in the result Map.
The class loader associated with the CharSequenceCompiler (see Listing 3) is a ClassLoaderImpl instance that looks up the bytecode for a class in the JavaFileManagerImpl instance, returning the .class files created by the compiler:
Listing 3. CharSequenceCompiler (partial source listing)
public class CharSequenceCompiler<T> { private final ClassLoaderImpl classLoader; private final JavaCompiler compiler; private final List<String> options; private DiagnosticCollector<JavaFileObject> diagnostics; private final FileManagerImpl javaFileManager; public CharSequenceCompiler(ClassLoader loader, Iterable<String> options) { compiler = ToolProvider.getSystemJavaCompiler(); if (compiler == null) { throw new IllegalStateException( "Cannot find the system Java compiler. " + "Check that your class path includes tools.jar"); } classLoader = new ClassLoaderImpl(loader); diagnostics = new DiagnosticCollector<JavaFileObject>(); final JavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null); javaFileManager = new FileManagerImpl(fileManager, classLoader); this.options = new ArrayList<String>(); if (options != null) { for (String option : options) { this.options.add(option); } } } public synchronized Map<String, Class<T>> compile(final Map<String, CharSequence> classes, final DiagnosticCollector<JavaFileObject> diagnosticsList) throws CharSequenceCompilerException, ClassCastException { List<JavaFileObject> sources = new ArrayList<JavaFileObject>(); for (Entry<String, CharSequence> entry : classes.entrySet()) { String qualifiedClassName = entry.getKey(); CharSequence javaSource = entry.getValue(); if (javaSource != null) { final int dotPos = qualifiedClassName.lastIndexOf('.'); final String className = dotPos == -1 ? qualifiedClassName : qualifiedClassName.substring(dotPos + 1); final String packageName = dotPos == -1 ? "" : qualifiedClassName .substring(0, dotPos); final JavaFileObjectImpl source = new JavaFileObjectImpl(className, javaSource); sources.add(source); javaFileManager.putFileForInput(StandardLocation.SOURCE_PATH, packageName, className + ".java", source); } } final CompilationTask task = compiler.getTask(null, javaFileManager, diagnostics, options, null, sources); final Boolean result = task.call(); if (result == null || !result.booleanValue()) { throw new CharSequenceCompilerException("Compilation failed.", classes.keySet(), diagnostics); } try { Map<String, Class<T>> compiled = new HashMap<String, Class<T>>(); for (Entry<String, CharSequence> entry : classes.entrySet()) { String qualifiedClassName = entry.getKey(); final Class<T> newClass = loadClass(qualifiedClassName); compiled.put(qualifiedClassName, newClass); } return compiled; } catch (ClassNotFoundException e) { throw new CharSequenceCompilerException(classes.keySet(), e, diagnostics); } catch (IllegalArgumentException e) { throw new CharSequenceCompilerException(classes.keySet(), e, diagnostics); } catch (SecurityException e) { throw new CharSequenceCompilerException(classes.keySet(), e, diagnostics); } } } |
|
Now that I have a simple API for compiling source, I'll put it in action by creating a function-plotting application, written in Swing. Figure 2 shows the application plotting the x * sin(x) * cos(x) function:
Figure 2. A dynamic application using the javaxtools.compiler package
The application uses the Function interface defined in Listing 4:
Listing 4. Function interface
package javaxtools.compiler.examples.plotter; public interface Function { double f(double x); } |
The application provides a text field in which the user can enter a Java expression that returns a double value based on an implicitly declared double x input parameter. The application inserts that expression text into the code template shown in Listing 5, at the location marked $expression. It also generates a unique class name each time, replacing $className in the template. The package name is also a template variable.
Listing 5. Function template
package $packageName; import static java.lang.Math.*; public class $className implements javaxtools.compiler.examples.plotter.Function { public double f(double x) { return ($expression) ; } } |
The application fills in the template via fillTemplate(packageName, className, expr), which returns a String object it then compiles using the CharSequenceCompiler. Exceptions or compiler diagnostics are passed to the log() method or written directly into the scrollable errors component in the application.
The newFunction() method shown in Listing 6 returns an object that implements the Function interface (see the source template in Listing 5):
Listing 6. Plotter's Function newFunction(String expr) method
Function newFunction(final String expr) { errors.setText(""); try { // generate semi-secure unique package and class names final String packageName = PACKAGE_NAME + digits(); final String className = "Fx_" + (classNameSuffix++) + digits(); final String qName = packageName + '.' + className; // generate the source class as String final String source = fillTemplate(packageName, className, expr); // compile the generated Java source final DiagnosticCollector<JavaFileObject> errs = new DiagnosticCollector<JavaFileObject>(); Class<Function> compiledFunction = stringCompiler.compile(qName, source, errs, new Class<?>[] { Function.class }); log(errs); return compiledFunction.newInstance(); } catch (CharSequenceCompilerException e) { log(e.getDiagnostics()); } catch (InstantiationException e) { errors.setText(e.getMessage()); } catch (IllegalAccessException e) { errors.setText(e.getMessage()); } catch (IOException e) { errors.setText(e.getMessage()); } return NULL_FUNCTION; } |
You'll typically generate source classes that extend a known base class or implement a specific interface, so that you can cast the instances to a known type and invoke its methods through a type-safe API. Note that the Function class is used as the generic type parameter T when instantiating the CharSequenceCompiler<T>. This allows the compiledFunction likewise to be typed as Class<Function> and compiledFunction.newInstance() to return a Function instance without requiring casts.
Once it has dynamically generated a Function instance, the application uses it to generate y values for a range of x values and then plot the (x,y) values using the open source JFreeChart API (see Resources). The full source of the Swing application is available in the downloadable source in the javaxtools.compiler.examples.plotter package.
This application's source code generation needs are quite modest. Other applications will benefit from a more sophisticated source template facility, such as Apache Velocity (see Resources).
|
An application that allows arbitrary Java source code to be entered by the user has some inherent security risks. Analogous to SQL injection (see Resources), a system that allows a user or other agent to supply raw Java source for code generation can be exploited maliciously. For example, in the Plotter application presented here, a valid Java expression can contain anonymous nested classes that access system resources, spawn threads for denial-of-service attacks, or perform other exploits. This exploit can be termed Java injection. Such applications should not be deployed in an insecure location in which an untrusted user can access it (such as on a Java EE server as a servlet, or as an applet). Instead, most clients of javax.tools should restrict the user input and translate user requests into secure source code.
Strategies for preserving security when using this package include:
- Use a custom SecurityManager or ClassLoader that prevents loading of anonymous classes or other classes not under your direct control.
- Use a source-code scanner or other preprocessor that discards input that uses questionable code constructs. For example, the Plotter can use a java.io.StreamTokenizer and discard input that includes a { (left brace) character, effectively preventing the declaration of anonymous or nested classes.
- Using the javax.tools API, the JavaFileManager can discard writing of any CLASS file that's unexpected. For example, when compiling a specific class, the JavaFileManager can throw a SecurityExeception for any other calls to store unexpected class files and allow only generated package and class names that the user can't guess or spoof. This is the strategy used by the Plotter's newFunction method.
发表评论
-
使用Spring 的封装的MailSender
2010-11-29 22:24 6727使用Spring 的封装的Ma ... -
有时候,SVN 上代码太多,而我们只想下载自己负责的那个部分进行修改,这时可以这样
2010-09-04 09:06 1275svn checkout <url_of_big_dir ... -
tomcat session replication on linux server.
2010-07-26 10:49 1197Specially, to turn on multicast ... -
Session lost when app. is redeployed (Solved)
2010-07-07 16:02 1267There is a workaround to this p ... -
jvm 5.0 GC 回收机制
2009-10-16 11:55 1771http://java.sun.com/docs/hotspo ... -
How to Create a Custom Annotations?
2009-10-08 11:32 1231There are a lot of documentatio ... -
JAXB 深入学习<1>
2009-08-04 22:22 2353说白了就是一个api将 xml+schema->ja ... -
simple json lib for java
2009-08-04 21:57 3223有时候为了需要将一个对象或数组转成json string 给前 ... -
在servlet 上输出图片
2008-07-30 21:38 4288public void doGet(HttpServletRe ... -
用java 对 oracle 中的 image 存取
2008-07-30 21:35 1855package data; import java.io. ... -
有关 java 的 tnameserv的link
2008-07-15 22:39 2299http://java.sun.com/j2se/1.4.2/ ... -
SOAP and JDOM
2008-06-18 21:54 2151看完上一篇 blog: Web 服务搜 ... -
Java Reflection API 运用示例
2008-05-05 15:51 2388本文节选 ... -
将系统移植到Spring
2008-04-29 11:06 1487Spring已经是一个在Apache 2.0许可下发布的基础构 ... -
动态代理一例
2008-04-28 15:33 1214在之前的一篇关于Dec ... -
使用JAVA中的动态代理实现数据库连接池
2008-04-28 13:48 1478作者通过使用JAVA中的动 ... -
Have you known enough about DBCP?
2008-04-23 12:08 2260Have you known enough about DBC ... -
AX-RPC Evolves into Simpler, More Powerful JAX-WS
2008-03-23 15:40 3556s of version 2.0, JAX-RPC has b ... -
更改 Netbeans 界面的字体大小
2008-03-22 07:29 4695学习或者使用 Netbeans 的时候, 有时候觉得界面字体很 ... -
JSF+Spring+Hibernate的实例讲解
2008-03-20 16:41 2452我一直认为jsf必定会成为MS的 Net ...
相关推荐
在Java开发中,`javax.mail`库是一个非常重要的组件,主要用于处理电子邮件的发送与接收。这个库提供了丰富的API,使得开发者能够轻松地实现邮件服务的功能。`javax.mail-1.6.0.jar`是该库的一个特定版本,包含了...
Classes contained in javax.jms.jar: javax.transaction.xa.XAResource.class javax.jms.BytesMessage.class javax.jms.Message.class javax.jms.JMSException.class javax.jms.Destination.class javax.jms....
javax.jms.BytesMessage.class javax.jms.Connection.class javax.jms.ConnectionConsumer.class javax.jms.ConnectionFactory.class javax.jms.ConnectionMetaData.class javax.jms.DeliveryMode.class javax.jms....
Files contained in javax.persistence.jar: META-INF/MANIFEST.MF javax.persistence.Access.class javax.persistence.AccessType.class javax.persistence.AssociationOverride.class javax.persistence....
Files contained in javax.ejb.jar: META-INF/MANIFEST.MF javax.ejb.AccessLocalException.class javax.ejb.AccessTimeout.class javax.ejb.ActivationConfigProperty.class javax.ejb.AfterBegin.class javax....
javax.jar javax.jar javax.jar javax.jar javax.jar javax.jar javax.jar javax.jar javax.jar javax.jar javax.jar javax.jar javax.jar javax.jar javax.jar javax.jar javax.jar javax.jar javax.jar javax.jar ...
当你遇到“找不到javax.servlet.*”这样的错误时,通常是因为你的项目缺少了这个库,所以需要引入`javax.servlet.jar`来解决问题。 1. **Java Servlet简介** Java Servlet是Java平台上的一个标准,用于扩展服务器...
Files contained in javax.servlet.jar: META-INF/MANIFEST.MF javax/servlet/http/LocalStrings.properties javax.servlet.http.HttpSessionBindingListener.class javax.servlet....
6. XML处理:增强了XML解析和转换功能,例如`javax.xml.bind`包提供了数据绑定框架,使Java对象与XML文档之间的转换更方便。 安装JDK 1.6 on Windows x64平台的步骤非常简单: 1. 解压缩"java-jdk1.6-jdk-6u45-...
META-INF / maven / org.glassfish.main.ejb / javax.ejb / pom.properties META-INF / maven / org.glassfish.main.ejb / javax.ejb / pom.xml javax.ejb.AccessLocalException.class javax.ejb.AccessTimeout....
通过java扩展包javax.mail-1.4.4.jar实现邮件发送功能。 import javax.mail.Address; import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart...
"javax.xml.rpc"是Java平台中的一个关键组件,主要用于实现基于XML的远程过程调用(XML-RPC)服务。这个框架允许Java应用程序通过HTTP协议来调用远程服务器上的方法,从而实现分布式计算。在Java EE环境中,它常与...
赠送jar包:javax.ws.rs-api-2.0.jar; 赠送原API文档:javax.ws.rs-api-2.0-javadoc.jar; 赠送源代码:javax.ws.rs-api-2.0-sources.jar; 赠送Maven依赖信息文件:javax.ws.rs-api-2.0.pom; 包含翻译后的API文档...
在Android Studio中遇到"Unable to load class ‘javax.xml.bind.JAXBException‘"的错误,通常是由于Java运行时环境(JRE)或开发工具包(JDK)与项目的兼容性问题导致的。`javax.xml.bind.JAXBException`是Java的...
赠送jar包:javax.mail-1.6.2.jar; 赠送原API文档:javax.mail-1.6.2-javadoc.jar; 赠送源代码:javax.mail-1.6.2-sources.jar; 赠送Maven依赖信息文件:javax.mail-1.6.2.pom; 包含翻译后的API文档:javax.mail...
【标题】"javax.xml.bind.jar" 是一个Java开发中常用的工具包,主要包含了Java对象到XML数据绑定的API,这是Java标准版(Java SE)的一部分,用于帮助开发者将Java类和XML文档之间的转换自动化,从而简化了XML处理。...
赠送jar包:javax.ws.rs-api-2.0.1.jar; 赠送原API文档:javax.ws.rs-api-2.0.1-javadoc.jar; 赠送源代码:javax.ws.rs-api-2.0.1-sources.jar; 赠送Maven依赖信息文件:javax.ws.rs-api-2.0.1.pom; 包含翻译后...
5. **脚本引擎支持**:通过`javax.script`包支持脚本语言的嵌入式执行,方便开发者编写混合Java和其他脚本语言的应用程序。 ### 三、JDK1.6的下载与安装 #### 下载方式 - **官方渠道**:通常推荐从Oracle官方网站...
7. **Swing与AWT**:在GUI编程方面,JDK 1.6提供了`javax.swing`和`java.awt`包,它们包含了大量的组件和布局管理器,使得开发者能够构建功能丰富的图形用户界面。 总之,JDK 1.6的CHM文档是开发者深入理解JDK 1.6...
描述中提到的“解决javax.xml jar包缺失的问题,引进javax.xml.rpc-api-1.1.1.jar”,意味着在开发或运行某个Java项目时,可能会遇到由于缺少`javax.xml.rpc`相关的jar包导致的编译或运行错误。为了解决这个问题,...