【问题标题】:DCH class error with JavaMailJavaMail 的 DCH 类错误
【发布时间】:2017-07-27 23:30:18
【问题描述】:

我正在尝试使用 Glassfish 3.1 提供的 jar 文件在 Java EE 6 中使用 JavaMail 设置一个简单的日志记录测试。关于这个主题似乎有很多问题,但我还没有找到任何有帮助的答案。我的测试代码如下所示:

import java.util.logging.Logger;

public class MyClass {
  private static final Logger LOGGER = Logger.getLogger("MyClass");

  public static void main(String[] args) {
    LOGGER.severe("This is a test");
  }
}

我的 logging.properties 文件包含以下内容:

com.sun.mail.util.logging.MailHandler.mail.smtp.host={my mail hub FQDN}
com.sun.mail.util.logging.MailHandler.mail.smtp.port=25
com.sun.mail.util.logging.MailHandler.mail.to={me}
com.sun.mail.util.logging.MailHandler.mail.from={support address}
com.sun.mail.util.logging.MailHandler.level=WARNING
com.sun.mail.util.logging.MailHandler.verify=local
com.sun.mail.util.logging.MailHandler.subject=Application Error
com.sun.mail.util.logging.MailHandler.formatter=java.util.logging.SimpleFormatter

我使用以下方法构建课程:

javac -cp $AS_INSTALL/glassfish/modules/javax.mail.jar:$AS_INSTALL/install/lib/external/jaxb/activation.jar:. MyClass.java

然后我使用以下命令运行程序:

java -cp $AS_INSTALL/glassfish/modules/javax.mail.jar:$AS_INSTALL/install/lib/external/jaxb/activation.jar:. -Djava.util.logging.config.file=logging.properties MyClass

这会导致以下错误:

Sep 22, 2011 4:19:25 PM MyClass main
SEVERE: This is a test
java.util.logging.ErrorManager: 3: SEVERE: no object DCH for MIME type multipart/mixed;
        boundary="----=_Part_1_26867996.1316722766145"
javax.activation.UnsupportedDataTypeException: no object DCH for MIME type multipart/mixed;
        boundary="----=_Part_1_26867996.1316722766145"
        at javax.activation.ObjectDataContentHandler.writeTo(DataHandler.java:877)
        at javax.activation.DataHandler.writeTo(DataHandler.java:302)
        at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1476)
        at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1772)
        at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1748)
        at com.sun.mail.util.logging.MailHandler.toRawString(MailHandler.java:2196)
        at com.sun.mail.util.logging.MailHandler.send(MailHandler.java:1597)
        at com.sun.mail.util.logging.MailHandler.close(MailHandler.java:552)
        at java.util.logging.LogManager.resetLogger(LogManager.java:693)
        at java.util.logging.LogManager.reset(LogManager.java:676)
        at java.util.logging.LogManager$Cleaner.run(LogManager.java:221)

javax.mail.MessagingException: IOException while sending message;
  nested exception is:
        javax.activation.UnsupportedDataTypeException: no object DCH for MIME type multipart/mixed;
        boundary="----=_Part_1_26867996.1316722766145"
        at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1141)
        at javax.mail.Transport.send0(Transport.java:195)
        at javax.mail.Transport.send(Transport.java:124)
        at com.sun.mail.util.logging.MailHandler.send(MailHandler.java:1594)
        at com.sun.mail.util.logging.MailHandler.close(MailHandler.java:552)
        at java.util.logging.LogManager.resetLogger(LogManager.java:693)
        at java.util.logging.LogManager.reset(LogManager.java:676)
        at java.util.logging.LogManager$Cleaner.run(LogManager.java:221)
Caused by: javax.activation.UnsupportedDataTypeException: no object DCH for MIME type multipart/mixed;
        boundary="----=_Part_1_26867996.1316722766145"
        at javax.activation.ObjectDataContentHandler.writeTo(DataHandler.java:877)
        at javax.activation.DataHandler.writeTo(DataHandler.java:302)
        at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1476)
        at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1772)
        at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1099)
        ... 7 more

我已验证我的 javax.mail.jar 文件包含多部分处理程序:

unzip -l $AS_INSTALL/glassfish/modules/javax.mail.jar | grep multipart
     2617  01-14-2011 15:37   com/sun/mail/handlers/multipart_mixed.class

我什至在启用激活调试的情况下运行程序。这向我展示了以下相关部分:

parse: multipart/*;;            x-java-content-handler=com.sun.mail.handlers.multipart_mixed; x-java-fallback-entry=true
  Type: multipart/*
    Command: content-handler, Class: com.sun.mail.handlers.multipart_mixed

MailcapCommandMap: createDataContentHandler for multipart/mixed
  search DB #1
  search DB #2
  search fallback DB #1
    got content-handler
      class com.sun.mail.handlers.multipart_mixed
Can't load DCH com.sun.mail.handlers.multipart_mixed; Exception: java.lang.ClassNotFoundException: com/sun/mail/handlers/multipart_mixed

我什至得到了上述文本/纯文本类型的副本。

MailcapCommandMap: createDataContentHandler for text/plain
  search DB #1
    got content-handler
      class com.sun.mail.handlers.text_plain
Can't load DCH com.sun.mail.handlers.text_plain; Exception: java.lang.ClassNotFoundException: com/sun/mail/handlers/text_plain

我在这里错过了什么?

谢谢, 史蒂夫

【问题讨论】:

  • 我要补充一点,这是一个 Solaris 10 系统。这是我的 JRE 版本:[/usr/jdk/instances/jdk1.6.0]: java -version java version "1.6.0_24" Java(TM) SE Runtime Environment (build 1.6.0_24-b07) Java HotSpot(TM) Server VM (构建 19.1-b02,混合模式)

标签: logging glassfish jakarta-mail java-ee-6


【解决方案1】:

在发送消息之前添加这些:

MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
        mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
        mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
        mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
        mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
        mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
        CommandMap.setDefaultCommandMap(mc);

我在我的 Android 应用程序中遇到了问题,它可以正常工作。

【讨论】:

  • 它在我的开发环境下 eclipse/linux/open-jdk6 下也得到了修复。
  • 我更喜欢这个解决方案而不是修改 bootclasspath,因为更改 bootclasspath 并不总是一种选择,例如:Java Web Start (JNLP)。
  • 谢谢,这在 Linux / Tomat6 / jdk6 上也能正常工作
【解决方案2】:

在我的情况下,我可以通过在 send() 之前添加它来解决这个问题:

Thread.currentThread().setContextClassLoader( getClass().getClassLoader() );

这是链接博客中建议的,因此如果您想了解更多详细信息,请阅读它。感谢 Jerry Gu 将其链接到此处和原始博主。

网址:http://blog.hpxn.net/2009/12/02/tomcat-java-6-and-javamail-cant-load-dch/

【讨论】:

  • 感谢上下文,因为 URL 现在似乎已死。
【解决方案3】:

我在这里找到了解决方案:

http://blog.hpxn.net/2009/12/02/tomcat-java-6-and-javamail-cant-load-dch/

虽然我很想知道更多关于为什么这是一个问题的细节以及这个 -Xbootclasspath 选项正在做什么来纠正这个问题。如果我这样上课:

java -Djava.util.logging.config.file=logging.properties -Xbootclasspath/p:/app/glassfish-3.1/glassfish/modules/javax.mail.jar MyClass

它会找到必要的课程,然后我会收到电子邮件。现在我只需要弄清楚如何将此配置转换为我的 Glassfish 服务器,并从这个简单的测试用例中尝试更“真实”的测试。

【讨论】:

  • 附加信息:一旦我将 -Xbootclasspath/p:${com.sun.aas.installRoot}/modules/javax.mail.jar 添加到 Glassfish 域上的 JVM 选项,并使用上述信息更新了 $AS_INSTALL/glassfish/domains/{domain}/config/logging.properties 文件,我会定期收到电子邮件通知,其中包含警告和以上。
【解决方案4】:

虽然我很想知道更多关于为什么这是一个问题背后的细节以及这个 -Xbootclasspath 选项正在做什么来纠正这个问题。

它与类加载器树有关。回想一下,允许子类加载器在父类加载器中查找类,但反之则不行。在您的示例程序中,类加载器树如下所示:

Running under JDK6, JDK7, and JDK8
+---Boot ClassLoader--+
| java.util.logging.* |
| javax.activation .* |
+---------------------+
          ^
          |
+-----System ClassLoader------+
| javax.mail.*                |
| com.sun.mail.handlers.*     |
| com.sun.mail.util.logging.* |
+-----------------------------+

LogManager$Cleaner 关闭挂钩运行 (JDK6+) 时,context classloader 被强制为 boot classloader,因为它位于子类加载器中,所以无法找到 com.sun.mail.handlers.text_plain 类。因此,modifying the MailcapCommandMap to include the mailcap class names 无法解决问题。当您使用-Xbootclasspath 选项时,您会将所有相关类放置在LogManager$Cleaner 可见的引导类加载器中。但是,请勿修改您的系统以使用-Xbootclasspath 来解决此问题。

相反,升级到包含Bug K6552 | GH133 - Use classloader ergonomics in the MailHandler 修复程序的JavaMail 1.5.3 或更高版本。如果要升级 GlassFish 的 JavaMail 模块,可以将 glassfish-X.X/glassfish/modules/javax.mail.jar 替换为更新版本的 JavaMail。

应用于 JavaMail 1.4.7 的不完整 fix 是将上下文类加载器设置为在关闭期间加载 MailHandler 的类加载器。假设加载MailHandler的类加载器应该能够找到激活码。

如果您无法升级到较新版本的 JavaMail,那么您必须应用以下解决方法之一:

  1. 在清理程序运行之前刷新或关闭 MailHandler。
  2. 在清理程序运行之前刷新所有处理程序(即取消部署 Web 应用程序)。您必须在 LogManager 上同步并从每个记录器收集所有处理程序。刷新同步块之外的所有处理程序。
  3. 如果上下文类加载器为空,则扩展 MailHandler 并覆盖 close 以设置和恢复上下文类加载器。
  4. 如果上下文类加载器为空,则安装新的 LogManager 并覆盖 reset 以设置和恢复上下文类加载器。
  5. 如果清理程序正在运行,请安装主题格式化程序以设置上下文类加载器。
  6. 将推送级别设置为ALL 或将容量设置为1,以便为每条日志记录发送一封电子邮件并发送垃圾邮件。
  7. 在带有 RFE JDK-8025251 补丁的 Java 版本上运行。

主要问题是LogManager$Cleaner 强制上下文类加载器在调用close 之前为每个Handler 注册LogManager。 LogManager 的更好选择是在调用 close 之前将上下文类加载器设置为处理程序类加载器,然后在所有处理程序关闭后将上下文类加载器设置为 null。这仍然可能被嵌套处理程序所愚弄,但至少它可以解决常见情况。这被归档为 RFE JDK-8025251“LogManager 清理器应在关闭期间使用处理程序类加载器”。

【讨论】:

    【解决方案5】:

    如果您在 KARAF(OSGI) 服务器上工作,上述建议很可能难以实施,因为 Karaf 没有启动类或启动类路径。

    我发现activation.jar 冲突造成了这个问题。

    {FUSEESB_HOME Or ServiceMIX_HOME}/etc/jre.properties was loading activation.jar .
    

    一旦评论一切顺利。

    请参考the link below

    【讨论】:

      【解决方案6】:

      我今天碰到这个问题,和线程的类加载器有关。

      如果您在以下位置进行系统输出: com.sun.mail.handlers.multipart_mixed.class.getClassLoader()

      它可能与当前线程的类加载器不同: Thread.currentThread().getContextClassLoader()

      我能够通过添加以下参数得出这个结论: -Djavax.activation.debug=true

      添加该参数后,我看到它无法为 multipart_mixed.class 加载数据内容处理程序 (DCH)。

      如何解决类加载器问题取决于您,但这应该可以帮助您入门。

      【讨论】:

        【解决方案7】:

        对于上面所有出现此错误消息,事实证明,在我的情况下,身份验证数据为空,这是因为我关闭了邮件服务器身份验证,我不再需要用户名和密码,但空值是以某种方式解析并创建了一个丢失的身份验证错误,在 Mail 1.4.0 中没有很好地捕捉到,更新到 Mail 1.4.7删除下面的两个参数条目解决了这个问题.

        <appender name="ALARM_MAIL" class="my.utils.SMTPAppender">
          <!-- remove this line: <param name="SMTPUsername" value=""/> -->
          <!-- remove this line: <param name="SMTPPassword" value=""/> -->
          ...
        

        【讨论】:

          猜你喜欢
          • 2010-12-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-01-11
          • 1970-01-01
          • 2010-10-10
          • 2012-03-14
          相关资源
          最近更新 更多