JVM 在尝试声明已声明的打印机 JavaPOS EPSON 热敏打印机时崩溃。

huangapple go评论62阅读模式
英文:

JVM crashes when trying to claim a claimed printer JavaPOS EPSON Thermal Printer

问题

以下是翻译好的内容:

import jpos.JposException;
import jpos.POSPrinter;
import jpos.util.JposPropertiesConst;

import java.time.Duration;
import java.time.Instant;

public class POSPrinterClaimTest {
  static POSPrinter posPrinter;

  private static Boolean isOpen = false;
  private static Boolean isClaimed = false;
  private static Boolean isEnabled = false;

  static {
    System.setProperty(
        JposPropertiesConst.JPOS_POPULATOR_FILE_PROP_NAME, "jpos.xml");
  }

  public static void main(String[] args) {
    try {
      posPrinter = new POSPrinter();
      Instant start = Instant.now();
      Instant finish = null;
      Long timeElapsed = null;
      openConnection("POSPrinter1");
      finish = Instant.now();
      timeElapsed = Duration.between(start, finish).toMillis();
      System.out.println("连接所用时间: " + timeElapsed.toString());
      Thread.sleep(100000L);
      terminate();
      System.out.println("从 try 块中终止");
    } catch (JposException | InterruptedException e) {
      e.printStackTrace();
      try {
        terminate();
        System.out.println("从 catch 块中终止");
        Thread.sleep(5000);
      } catch (JposException | InterruptedException jposException) {
        jposException.printStackTrace();
      }
    } catch(Throwable t){
      t.printStackTrace();
    } finally {
      posPrinter = null;
    }
  }

  private static void openConnection(String printerName) throws JposException {
    try {
      String printerNamesss = printerName;
      /**
       * 根据 jpos.xml 中定义的设备逻辑名称打开打印机对象
       */
      posPrinter.open(printerName);
      isOpen = true;
      System.out.println("已打开");
      /**
       * 获得已打开设备的独占控制权。
       * 此时设备被其他应用程序禁用。
       */
      posPrinter.claim(3000);
      isClaimed = true;
      System.out.println("已获得控制权");
      /**
       * 启用设备的输入和输出
       */
      posPrinter.setDeviceEnabled(true);
      isEnabled = true;
      System.out.println("已启用");

    } catch (JposException jposException) {
      System.out.println("在打开中发生 jpos 异常: " + jposException.getMessage());
      throw jposException;
    } catch(Throwable t) {
      System.out.println("在打开中发生未知异常: " + t.getMessage());
    }
  }

  public static void terminate() throws JposException {
    try {
        if(isOpen && isClaimed) {
          posPrinter.clearOutput();
          System.out.println("已清除输出");
        }

        if(isEnabled) {
          posPrinter.setDeviceEnabled(false);
          isEnabled = false;
          System.out.println("设备已禁用");
        }

        if(isClaimed) {
          posPrinter.release();
          isClaimed = false;
          System.out.println("已释放");
        }

        if(isOpen) {
          posPrinter.close();
          isOpen = false;
          System.out.println("已关闭");
        }
    } catch (JposException jposException) {
      jposException.printStackTrace();
      throw jposException;
    } catch(Throwable t) {
      System.out.println("在终止中发生未知异常: " + t.getMessage());
    }
  }
}

第一个进程输出:

已打开
已获得控制权
已启用
连接所用时间: 7928 --> 现在我开始第二个进程。
已清除输出
设备已禁用
已释放
已关闭
从 try 块中终止

第二个进程输出:

已打开
在打开中发生 jpos 异常: The port is already open.
jpos.JposException: The port is already open.
at jp.co.epson.upos.core.v1_14_0001.pntr.CommonUPOSExceptionCreator.createJposException(CommonUPOSExceptionCreator.java:138)
at jp.co.epson.upos.core.v1_14_0001.pntr.CommonUPOSExceptionCreator.createJposException(CommonUPOSExceptionCreator.java:99)
at jp.co.epson.upos.core.v1_14_0001.pntr.CommonPrinterService.openPort(CommonPrinterService.java:3341)
at jp.co.epson.upos.core.v1_14_0001.pntr.CommonPrinterService.claim(CommonPrinterService.java:3103)
at jpos.BaseJposControl.claim(Unknown Source)
at POSPrinterClaimTestThreads.openConnection(POSPrinterClaimTestThreads.java:73)
at POSPrinterClaimTestThreads.test(POSPrinterClaimTestThreads.java:36)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
已关闭
从 catch 块中终止
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f43880ea9df, pid=12119, tid=0x00007f43690b0700
# ...
英文:

I am using Epson_JavaPOS_ADK_11414_for_Linux_x64 for installing the JavaPOS with pcs ( sh installJavaPOSFull-64.sh )

I ran this program one after the other in different shells and the second process crashes for some reason:

import jpos.JposException;
import jpos.POSPrinter;
import jpos.util.JposPropertiesConst;

import java.time.Duration;
import java.time.Instant;

public class POSPrinterClaimTest {
  static POSPrinter posPrinter;

  private static Boolean isOpen = false;
  private static Boolean isClaimed = false;
  private static Boolean isEnabled = false;



  static {
    System.setProperty(
        JposPropertiesConst.JPOS_POPULATOR_FILE_PROP_NAME, "jpos.xml");
  }

  public static void main(String[] args) {
    try {
      posPrinter = new POSPrinter();
      Instant start = Instant.now();
      Instant finish = null;
      Long timeElapsed = null;
      openConnection("POSPrinter1");
      finish = Instant.now();
      timeElapsed = Duration.between(start, finish).toMillis();
      System.out.println("Time taken to connect : " + timeElapsed.toString());
      Thread.sleep(100000L);
      terminate();
      System.out.println("terminated from try block");
    } catch (JposException | InterruptedException e) {
      e.printStackTrace();
      try {
        terminate();
        System.out.println("terminated from catch block");
        Thread.sleep(5000);
      } catch (JposException | InterruptedException jposException) {
        jposException.printStackTrace();
      }
    } catch(Throwable t){
      t.printStackTrace();
    } finally {
      posPrinter = null;
    }
  }

  private static void openConnection(String printerName) throws JposException {
    try {

      String printerNamesss = printerName;
      /**
       * open the printer object according to the device logical name defined in jpos.xml
       */
      posPrinter.open(printerName);
      isOpen = true;
      System.out.println("opened");
      /**
       * Get the exclusive control right for the opened device.
       * Then the device is disable from other application.
       * */
      posPrinter.claim(3000);
      isClaimed = true;
      System.out.println("claimed");
      /**
       *  enable the device for input and output
       */
      posPrinter.setDeviceEnabled(true);
      isEnabled = true;
      System.out.println("enabled");

    } catch (JposException jposException) {
      System.out.println("jpos exception in open : " + jposException.getMessage());
      throw jposException;
    } catch(Throwable t) {
      System.out.println("unknown throwable open: " + t.getMessage());
    }
  }


  public static void terminate() throws JposException {
    try {
        if(isOpen && isClaimed) {
          posPrinter.clearOutput();
          System.out.println("cleared output");
        }

        if(isEnabled) {
          posPrinter.setDeviceEnabled(false);
          isEnabled = false;
          System.out.println("setDeviceEnabled false");
        }

        if(isClaimed) {
          posPrinter.release();
          isClaimed = false;
          System.out.println("released");
        }

        if(isOpen) {
          posPrinter.close();
          isOpen = false;
          System.out.println("closed");
        }
    } catch (JposException jposException) {
      jposException.printStackTrace();
      throw jposException;
    } catch(Throwable t) {
      System.out.println("unknown throwable terminate: " + t.getMessage());
    }
  }
}


First process output

opened
claimed
enabled
Time taken to connect : 7928 --> now I start the second process.
cleared output
setDeviceEnabled false
released
closed
terminated from try block

Second process output

opened
jpos exception in open : The port is already open.
jpos.JposException: The port is already open.
at jp.co.epson.upos.core.v1_14_0001.pntr.CommonUPOSExceptionCreator.createJposException(CommonUPOSExceptionCreator.java:138)
at jp.co.epson.upos.core.v1_14_0001.pntr.CommonUPOSExceptionCreator.createJposException(CommonUPOSExceptionCreator.java:99)
at jp.co.epson.upos.core.v1_14_0001.pntr.CommonPrinterService.openPort(CommonPrinterService.java:3341)
at jp.co.epson.upos.core.v1_14_0001.pntr.CommonPrinterService.claim(CommonPrinterService.java:3103)
at jpos.BaseJposControl.claim(Unknown Source)
at POSPrinterClaimTestThreads.openConnection(POSPrinterClaimTestThreads.java:73)
at POSPrinterClaimTestThreads.test(POSPrinterClaimTestThreads.java:36)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
closed
terminated from catch block
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f43880ea9df, pid=12119, tid=0x00007f43690b0700
#
# JRE version: OpenJDK Runtime Environment (8.0_252-b09) (build 1.8.0_252-b09)
# Java VM: OpenJDK 64-Bit Server VM (25.252-b09 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C  [libethernetio31.so+0x1f9df]  CCommonPort::PortEvent(unsigned int, unsigned int, unsigned int*, unsigned int, unsigned char*)+0xf
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /POSPrinterTest/JavaPOS/hs_err_pid12119.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#
Aborted

If you see the second process throws a JposException which then initiates its catch and closes the connection. Then it suddenly crashes instead of sleeping for 5sec.

Any help?

答案1

得分: 1

与 EPSON 团队讨论了这个问题之后,他们能够提供一个解决方案,其中包括一个新的 libepsonjpos.so 和 epsonjpos.jar 文件。

这解决了我遇到的两个问题:

  1. 文章中提到的原始问题 - 在使用最新的 libepsonjpos.so 后得到了解决。
  2. 在非安装模式(No-SetupPOS-install)的单个进程中进行多线程打印
    • Epson 团队建议在所有线程中同步使用 POSPrinter.open(),并使用他们的修复更新 epsonjpos.jar 文件。

以下是来自 Epson 团队关于这个问题的一些引用。

关于多线程问题 - “变更历史
已应用的修复程序位于设备共享逻辑中。仅影响轻量级模式(无安装版本)
不同的对象错误地被假定为相等。结果是只使用了第一个连接的打印机。
修复纠正了比较逻辑。”

关于索赔问题 - “我们很高兴我们能够帮助你。
至于问题的背景,使用非安装模式的多进程使用对于我们的 JavaPOS ADK 来说是一个边缘情况。在您的帮助下,我们能够改进我们的测试案例。”

Epson 团队表示他们将在下一个版本中发布这些补丁。

英文:

After discussing this problem with EPSON team, they were able to provide a fix for the same with a new libepsonjpos.so and epsonjpos.jar

It solved two problems for me:

  1. The original claim issue in the post - resolved after using the latest libepsonjpos.so
  2. Multi-threaded printing in a single process in non-install mode (No-SetupPOS-insall)
    • the Epson team said to synchronize the POSPrinter.open() in all the threads and update the epsonjpos.jar with their fix

Some quotes on the issue from Epson Team.

Multi-thread issue - "Change History
The fix that has been applied is in the device sharing logic. Only affects lite-mode (No-SetupPOS version)
The different objects falsely assumed as equal. As result only the first connected printer has been used.
The fix corrects that comparison logic."

Claim Issue - "We are glad we could help you.
As for the background of the issues. The multi-process usage with non-install mode was a corner case for our JavaPOS ADK. With your help we could improve our testing cases."

Epson team said that they will release the patches in the next version.

答案2

得分: 0

好的,以下是翻译好的内容:

似乎JavaPOS Service Object的独占控制处理效果不佳。

你应该会收到超时错误,而不是端口已经打开的错误。

然而,你的程序也有问题。
一个try、catch的范围太宽了。

JposException的形式是异常,但实际上只是一个错误代码通知。
仅仅因为出现了JposException并不意味着它会导致崩溃。
大多数情况下,如果消除了错误的原因并重试,它通常会正常工作。

要正确处理,尝试并捕获每个方法调用和属性访问。

Epson_JavaPOS_ADK示例程序应该是这样制作的。
请按照示例程序的方式编码。


此外:

你所看到的是否不同?
它会为每个方法和属性分别进行try和catch,而不会使用throw将其传播到顶层。
我拥有的一些资源:

来自"Epson_JavaPOS_ADK_11414_for_Linux_x64\Sample\Samples\Printer\PrinterSample_Step15\src\printersample_step15\Step15Frame.java":

// Step7的JavaPOS代码
// 设置OutputCompleteEvent监听器
ptr.addOutputCompleteListener(this);
// Step7的JavaPOS代码--结束

// Step10的JavaPOS代码
try {
// 打开设备。
// 使用连接到计算机的设备的名称。
ptr.open("POSPrinter");
}
catch(JposException ex){
JOptionPane.showMessageDialog(this, "该设备尚未注册,或无法使用。",
"",JOptionPane.WARNING_MESSAGE);
// 无法使用任何内容。
changeButtonStatus();
return;
}

try {
// 获取已打开设备的独占控制权。
// 然后该设备将被其他应用禁用。
ptr.claim(1000);
bCoverSensor = ptr.getCapCoverSensor();
}
catch(JposException ex){
JOptionPane.showMessageDialog(this, "无法获取设备的独占访问权限。",
"",JOptionPane.WARNING_MESSAGE);
// 无法使用任何内容。
changeButtonStatus();
return;
}


从评论中提取情况并发布:

好吧,由于Claim报告的错误可能是错误的,为什么不向EPSON支持部门提供关于这种情况的详细信息呢?

来自提问者:

已经这样做了,但我们不知道他们是否会回复。所以尝试在这里找到答案;不管怎样,试试看。 JVM 在尝试声明已声明的打印机 JavaPOS EPSON 热敏打印机时崩溃。

来自提问者:

我在单个进程中以两个脉冲的方式运行了相同的程序。如你所说,我现在确实收到了超时错误。只有在不同的进程场景下,我才会遇到崩溃。

如果是这样,可能是JavaPOS服务对象的进程间独占控制存在问题。这是问题所在,但崩溃可能是异常结束时的清理问题,就像我之前评论过的那样。当在Claim方法中发生异常时,不要通过传播异常来结束进程,而是调用Close方法并尝试其他清理工作以正常结束。

来自提问者:

我在claim的catch块中写了posPrinter.close()。这有效,当使用两个进程的单个线程执行时,崩溃频率显著减少。但在两个每个都有10个线程的进程中,尝试去声明打印机会导致一个进程能够声明,而另一个进程崩溃。try{ posPrinter.claim(3000); } catch(JposException ex) { posPrinter.close();}

似乎EPSON的JavaPOS服务对象的独占控制问题仍然存在。请根据这样的调查信息向EPSON进行更多的查询。

英文:

It seems that the exclusive control processing of JavaPOS Service Object does not work well.

You should get a timeout error instead of an error that the port is already open.

However, your program is also bad.
The range of one try, catch is too wide.

JposException takes the form of an exception, but it's really just an error code notification.
Just because a JposException was signaled does not mean it crashes.
Most of the time, it will work if you eliminate the cause of the error and try again.

To be correct, try and catch each method call and property access.

The Epson_JavaPOS_ADK sample program should have been made that way.
Please code the same as the sample program.


In Addition:

Is what you see different?
It does try and catch in small units for each method and property, and does not propagate it to the top with throw.
Some of the sources I have are:

from "Epson_JavaPOS_ADK_11414_for_Linux_x64\Sample\Samples\Printer\PrinterSample_Step15\src\printersample_step15\Step15Frame.java"

> // JavaPOS's code for Step7
> // Set OutputCompleteEvent listener
> ptr.addOutputCompleteListener(this);
> // JavaPOS's code for Step7--END
>
> // JavaPOS's code for Step10
> try {
> //Open the device.
> //Use the name of the device that connected with your computer.
> ptr.open("POSPrinter");
>
> }
> catch(JposException ex){
> JOptionPane.showMessageDialog(this, "This device has not been registered, or cannot use.",
> "",JOptionPane.WARNING_MESSAGE);
> //Nothing can be used.
> changeButtonStatus();
> return;
> }
>
> try {
> //Get the exclusive control right for the opened device.
> //Then the device is disable from other application.
> ptr.claim(1000);
> bCoverSensor = ptr.getCapCoverSensor();
> }
> catch(JposException ex){
> JOptionPane.showMessageDialog(this, "Fails to get the exclusive access for the device.",
> "",JOptionPane.WARNING_MESSAGE);
> //Nothing can be used.
> changeButtonStatus();
> return;
> }


Extracting the situation from the comment and posting:

Well, the error reported by Claim may be wrong, so why not contact EPSON support with detailed information about such a situation?

From OP:
>Done that already but we don't know if they will respond back. So trying to find answer here; somewhere. JVM 在尝试声明已声明的打印机 JavaPOS EPSON 热敏打印机时崩溃。

From OP:
>I ran the same program in a single process with multiple threads in two pulses. I do now get the timeout error as you said. Only in different processes scenario, I am getting a crash

If so, there may be a problem with the interprocess exclusive control of the JavaPOS service object. That's the problem with it, but the crash could be a cleanup issue at the end of the exception, as I commented earlier. When an exception occurs in the Claim method, instead of ending the process by propagating the exception, call the Close method and try other cleanup to end normally.

From OP:
>I wrote the posPrinter.close() in claim catch block. It worked and crash frequency reduced significantly when doing with two processes single threads. Still the crash happened once or twice. But in two processes each with 10 threads trying to claim printer results in one process able to claim and the other process crashing. try{ posPrinter.claim(3000); } catch(JposException ex) { posPrinter.close();}

It seems that the problem of exclusive control of JavaPOS service object of EPSON may remain. Please make additional inquiries to EPSON based on such survey information.

huangapple
  • 本文由 发表于 2020年9月6日 02:30:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/63757259.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定