简体   繁体   English

Raspberry PI 2 Java 8 JVM错误

[英]Raspberry PI 2 Java 8 JVM error

I am in the process of building a web app based on Java 1.8, spring, hibernate, mysql and using tomcat as web server. 我正在构建基于Java 1.8,spring,hibernate,mysql的Web应用程序,并使用tomcat作为Web服务器。 Right now my app is logging (@5 sec interval) the raspberry's system data like; 现在我的应用正在记录(每隔5秒)树莓的系统数据,例如: cpu temperature, cpu core voltage, used memory, free memory, memory buffers, etc. The problem is that from time to time the app is crashing because it's running out of memory and I can't identify the reason. cpu温度,cpu核心电压,已用内存,可用内存,内存缓冲区等。问题是应用程序不时崩溃是因为它的内存不足,我无法确定原因。

First, on tomcat I had the following lines in tomcat's startup service : 首先,在tomcat上,tomcat的启动服务中包含以下几行:

Environment='CATALINA_OPTS=-Xms256M -Xmx512M -server -XX:+UseParallelGC'
Environment='JAVA_OPTS=-Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom'

and it was crashing in about 8 hours after starting tomcat. 并且在启动tomcat之后约8小时内崩溃了。 I removed those lines and now it is crashing at about 2 days because it is out of memory. 我删除了这些行,现在由于内存不足,它在大约2天后崩溃了。 Today it was the first time when it crashed without those lines in starting script and my last line inserted in db was: 今天,这是它第一次崩溃,但启动脚本中没有这些行,而我在db中插入的最后一行是:

# id, cpuTemperature, cpuCoreVoltage, usedMemory, freeMemory, memoryBuffers, sdramCVoltage, sdramIVoltage, sdramPVoltage, createdAt, modifiedAt, createdBy, modifiedBy
'52414', '39',          '1.3125',    '958320640', '12447744', '92495872',        '1.2',         '1.2',       '1.225',     '2015-11-23 15:53:58', NULL, NULL, NULL

For this info I am using SystemInfo class from pi4j library. 对于此信息,我正在使用pi4j库中的SystemInfo类。 getMemoryUsed() is returning used memory in bits so after a simple math we obtain a used memory of 913.92 Mb. getMemoryUsed()返回以位为单位的已用内存,因此在简单的数学运算之后,我们得到的已用内存为913.92 Mb。

When app start, it is consuming only 250 Mb ram and after 3 day is crashing the app beacause it's reaching the maximum memory of the raspberry pi. 启动应用程序时,它仅消耗250 Mb的内存,而3天后崩溃的原因是应用程序达到了树莓派的最大内存。

Spring App Config: Spring App Config:

@Configuration
@EnableWebMvc
@EnableScheduling
@ComponentScan({"ro.i2cWebAppController.app.controller","ro.i2cWebAppController.app.serv","ro.i2cWebAppController.app.schedule"})
@Import({SpringSecurityConfig.class})
@EnableJpaRepositories({"ro.i2cWebAppController.app.repo"})
public class AppConfig extends WebMvcConfigurerAdapter {

    private static final Logger logger = Logger.getLogger(AppConfig.class);

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/res/**").addResourceLocations("/WEB-RES/");
        registry.addResourceHandler("/**/**.ico").addResourceLocations("/WEB-RES/img/favicon.ico");
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Bean
    public ViewResolver viewResolver(ContentNegotiationManager manager) {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

    @Bean(name = "entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean sessionFactory() {
        LocalContainerEntityManagerFactoryBean lcemfb = new LocalContainerEntityManagerFactoryBean();
        HibernateJpaVendorAdapter hjva = new HibernateJpaVendorAdapter();
        hjva.setShowSql(true);
        //persistence unit
        lcemfb.setDataSource(dataSource());
        lcemfb.setJpaVendorAdapter(hjva);
        lcemfb.setPackagesToScan("ro.i2cWebAppController.app.model");
        lcemfb.setJpaPropertyMap(hibernateProperties());
        return lcemfb;
    }

    @Bean
    public DataSource dataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        if(isUnix()){
            dataSource.setUrl("jdbc:mysql://localhost:3306/i2cwac?autoReconnect=true");
        }else{
            dataSource.setUrl("jdbc:mysql://192.168.1.30:3306/i2cwac?autoReconnect=true");
        }
        dataSource.setUsername("i2cwac");
        dataSource.setPassword("Stefan1234");
        dataSource.setInitialSize(5);
        dataSource.setMaxTotal(20);
        dataSource.setMaxIdle(10);
        dataSource.setMinIdle(5);
        dataSource.setMaxWaitMillis(2000);
        return dataSource;
    }

    @Bean
    @Autowired
    public JpaTransactionManager transactionManager(EntityManagerFactory lcemfb) {
        JpaTransactionManager txManager = new JpaTransactionManager();
        txManager.setEntityManagerFactory(lcemfb);

        return txManager;
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
        return new PersistenceExceptionTranslationPostProcessor();
    }

    Map<String,String> hibernateProperties() {
        Map<String,String> propMap = new HashMap<>();
        propMap.put("hibernate.hbm2ddl.auto", "validate");
        propMap.put("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
        propMap.put("hibernate.globally_quoted_identifiers", "true");
        propMap.put("hibernate.show_sql", "true");
        return propMap;
    }

    @Bean
    public Integer ambientTemperature(){
        return new Integer(0);
    }

    @Bean
    public SystemInformationService systemInformationService(){
        return new SystemInformationServiceImpl();
    }

    @Bean
    public Boolean isUnix(){
        if(System.getProperty("os.name").toLowerCase().indexOf("win")>=0){
            logger.info("isUnix : false because : " + System.getProperty("os.name"));
            return false;
        }else{
            logger.info("isUnix : true because : " + System.getProperty("os.name"));
            return true;
        }
    }

    @Bean
    public I2CBus i2CBus(){
        I2CBus i2CBus = null;
        if (isUnix()) {
            int count = 0;
            int maxTries = 10;
            while (true) {
                try {
                    i2CBus = I2CFactory.getInstance(I2CBus.BUS_1);
                    break;
                } catch (IOException e) {
                    ++count;
                    logger.error("I2CBUS try " + count);
                    if (count == maxTries) e.printStackTrace();
                }
            }
        }
        if (i2CBus == null){
            logger.info("I2CBUS is NULL");
        }else{
            logger.info("Got I2CBUS " + i2CBus.toString());
        }

        return i2CBus;
    }
}

Scheduler class: 调度程序类:

@Component
public class RaspberryPiScheduler {

    @Autowired
    SystemInformationService systemInformationService;

    @Autowired
    RaspberryPiDataService raspberryPiDataService;

    @Autowired
    Boolean isUnix;

    private static final Logger logger = Logger.getLogger(RaspberryPiScheduler.class);

    /**
     * Scheduled method to write data from Raspberry Pi sensors
     */
    @Scheduled(fixedDelay = 5000)
    public void writeRaspberryPiData(){
        logger.info("Insert raspberrypi stats");
        if(isUnix){
            try {
                raspberryPiDataService.save(new RaspberryPiData(
                        systemInformationService.getCpuTemperature(),
                        systemInformationService.getCpuVoltage(),
                        systemInformationService.getMemoryUsed(),
                        systemInformationService.getMemoryFree(),
                        systemInformationService.getMemoryBuffers(),
                        systemInformationService.getMemoryVoltageSDRam_C(),
                        systemInformationService.getMemoryVoltageSDRam_I(),
                        systemInformationService.getMemoryVoltageSDRam_P()
                        ));
            } catch (Exception e) {
                logger.error("writeRaspberryPiData error",e);
            }
        }

    }

}

Base Repo: 基本回购:

@NoRepositoryBean
public interface BaseRepo<T, ID extends Serializable> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
}

Right now I don't find the error in the log, but in the past it crashed with SIGILL error. 现在我在日志中找不到错误,但是在过去,它因SIGILL错误而崩溃。 I will edit this post after finding the log. 找到日志后,我将编辑此帖子。

I found the log with error from JVM: 我发现了来自JVM的错误日志:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGILL (0x4) at pc=0x741db028, pid=1918, tid=1620767840
#
# JRE version: Java(TM) SE Runtime Environment (8.0-b132) (build 1.8.0-b132)
# Java VM: Java HotSpot(TM) Server VM (25.0-b70 mixed mode linux-arm )
# Problematic frame:
# J 1635 C2 com.mysql.jdbc.ResultSetImpl.<init>(JJLcom/mysql/jdbc/MySQLConnection;Lcom/mysql/jdbc/StatementImpl;)V (314 bytes) @ 0x741db028 [0x741dae20+0x208]
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
#

---------------  T H R E A D  ---------------

Current thread (0x63003c00):  JavaThread "pool-2-thread-2" [_thread_in_Java, id=1967, stack(0x60960000,0x609b0000)]

siginfo:si_signo=SIGILL: si_errno=0, si_code=1 (ILL_ILLOPC), si_addr=0x741db028

Registers:
  r0  = 0x71897568
  r1  = 0x00000008
  r2  = 0x00000000
  r3  = 0x00000000
  r4  = 0x62922d40
  r5  = 0x00000368
  r6  = 0x693d65e8
  r7  = 0x62922d40
  r8  = 0x73a51000
  r9  = 0x66c13e30
  r10 = 0x63003c00
  fp  = 0x693d65e8
  r12 = 0x718974b8
  sp  = 0x609adfa0
  lr  = 0x73e74bb0
  pc  = 0x741db028
  cpsr = 0x60000010

Top of Stack: (sp=0x609adfa0)
0x609adfa0:   6e614d79 3d74696d 00000007 00000000
0x609adfb0:   609ae008 73e74bb0 00000000 00000000
0x609adfc0:   693d65e8 00000000 00000000 00000000
0x609adfd0:   693d65e8 00000000 00000000 00000000
0x609adfe0:   00000000 718974b8 609adfe8 629d07b7
0x609adff0:   609ae028 629d4420 602ed004 629d0800
0x609ae000:   609adfcc 609ae010 609ae04c 73e74bb0
0x609ae010:   00000000 693d65e8 00000000 00000000 

Instructions: (pc=0x741db028)
0x741db008:   e5d45008 e59cb05c e5cc5044 f57ff05f
0x741db018:   e59b4004 e1540007 1a00003a e3005368
0x741db028:   e18b40d5 e59c605c e1cc40f8 f57ff05f
0x741db038:   e5964004 e1540007 1a000036 e5964478 

Register to memory mapping:

  r0  = 0x71897568
0x71897568 is an oop
[Lcom.mysql.jdbc.Field; 
 - klass: 'com/mysql/jdbc/Field'[]
 - length: 0

  r1  = 0x00000008
0x00000008 is an unknown value

  r2  = 0x00000000
0x00000000 is an unknown value

  r3  = 0x00000000
0x00000000 is an unknown value

  r4  = 0x62922d40
0x62922d40 is an unknown value

  r5  = 0x00000368
0x00000368 is an unknown value

  r6  = 0x693d65e8
0x693d65e8 is an oop
com.mysql.jdbc.JDBC4Connection 
 - klass: 'com/mysql/jdbc/JDBC4Connection'

  r7  = 0x62922d40
0x62922d40 is an unknown value

  r8  = 0x73a51000
0x73a51000 is an unallocated location in the heap

  r9  = 0x66c13e30
0x66c13e30 is an unknown value

  r10 = 0x63003c00
0x63003c00 is a thread

  fp  = 0x693d65e8
0x693d65e8 is an oop
com.mysql.jdbc.JDBC4Connection 
 - klass: 'com/mysql/jdbc/JDBC4Connection'

  r12 = 0x718974b8
0x718974b8 is an oop
com.mysql.jdbc.JDBC42ResultSet 
 - klass: 'com/mysql/jdbc/JDBC42ResultSet'

  sp  = 0x609adfa0
0x609adfa0 is pointing into the stack for thread: 0x63003c00

  lr  = 0x73e74bb0
0x73e74bb0 is at code_begin+2176 in an Interpreter codelet
invoke return entry points  [0x73e74330, 0x73e74cc0]  2448 bytes

  pc  = 0x741db028
0x741db028 is at entry_point+520 in (nmethod*)0x741dad08



Stack: [0x60960000,0x609b0000],  sp=0x609adfa0,  free space=311k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
J 1635 C2 com.mysql.jdbc.ResultSetImpl.<init>(JJLcom/mysql/jdbc/MySQLConnection;Lcom/mysql/jdbc/StatementImpl;)V (314 bytes) @ 0x741db028 [0x741dae20+0x208]
j  com.mysql.jdbc.JDBC4ResultSet.<init>(JJLcom/mysql/jdbc/MySQLConnection;Lcom/mysql/jdbc/StatementImpl;)V+7
j  com.mysql.jdbc.JDBC42ResultSet.<init>(JJLcom/mysql/jdbc/MySQLConnection;Lcom/mysql/jdbc/StatementImpl;)V+7
j  sun.reflect.GeneratedConstructorAccessor17.newInstance([Ljava/lang/Object;)Ljava/lang/Object;+242
J 1634 C2 com.mysql.jdbc.ResultSetImpl.getInstance(JJLcom/mysql/jdbc/MySQLConnection;Lcom/mysql/jdbc/StatementImpl;)Lcom/mysql/jdbc/ResultSetImpl; (65 bytes) @ 0x741e0260 [0x741dff70+0x2f0]
j  com.mysql.jdbc.MysqlIO.buildResultSetWithUpdates(Lcom/mysql/jdbc/StatementImpl;Lcom/mysql/jdbc/Buffer;)Lcom/mysql/jdbc/ResultSetImpl;+170
j  com.mysql.jdbc.MysqlIO.readResultsForQueryOrUpdate(Lcom/mysql/jdbc/StatementImpl;IIIZLjava/lang/String;Lcom/mysql/jdbc/Buffer;ZJ[Lcom/mysql/jdbc/Field;)Lcom/mysql/jdbc/ResultSetImpl;+18
j  com.mysql.jdbc.MysqlIO.readAllResults(Lcom/mysql/jdbc/StatementImpl;IIIZLjava/lang/String;Lcom/mysql/jdbc/Buffer;ZJ[Lcom/mysql/jdbc/Field;)Lcom/mysql/jdbc/ResultSetImpl;+30
j  com.mysql.jdbc.MysqlIO.sqlQueryDirect(Lcom/mysql/jdbc/StatementImpl;Ljava/lang/String;Ljava/lang/String;Lcom/mysql/jdbc/Buffer;IIIZLjava/lang/String;[Lcom/mysql/jdbc/Field;)Lcom/mysql/jdbc/ResultSetInternalMethods;+806
J 1596 C2 com.mysql.jdbc.ConnectionImpl.execSQL(Lcom/mysql/jdbc/StatementImpl;Ljava/lang/String;ILcom/mysql/jdbc/Buffer;IIZLjava/lang/String;[Lcom/mysql/jdbc/Field;Z)Lcom/mysql/jdbc/ResultSetInternalMethods; (426 bytes) @ 0x741cb6d8 [0x741cb3f0+0x2e8]
j  com.mysql.jdbc.ConnectionImpl.setAutoCommit(Z)V+147
j  org.apache.commons.dbcp2.DelegatingConnection.setAutoCommit(Z)V+9
j  org.apache.commons.dbcp2.DelegatingConnection.setAutoCommit(Z)V+9
j  org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.begin()V+13
j  org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.begin()V+12
j  org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.begin()V+8
j  org.hibernate.engine.transaction.internal.TransactionImpl.begin()V+47
j  org.hibernate.internal.SessionImpl.beginTransaction()Lorg/hibernate/Transaction;+41
j  org.hibernate.jpa.internal.TransactionImpl.begin()V+42
j  org.springframework.orm.jpa.DefaultJpaDialect.beginTransaction(Ljavax/persistence/EntityManager;Lorg/springframework/transaction/TransactionDefinition;)Ljava/lang/Object;+26
j  org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(Ljavax/persistence/EntityManager;Lorg/springframework/transaction/TransactionDefinition;)Ljava/lang/Object;+34
j  org.springframework.orm.jpa.JpaTransactionManager.doBegin(Ljava/lang/Object;Lorg/springframework/transaction/TransactionDefinition;)V+148
j  org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(Lorg/springframework/transaction/TransactionDefinition;)Lorg/springframework/transaction/TransactionStatus;+204
j  org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(Lorg/springframework/transaction/PlatformTransactionManager;Lorg/springframework/transaction/interceptor/TransactionAttribute;Ljava/lang/String;)Lorg/springframework/transaction/interceptor/TransactionAspectSupport$TransactionInfo;+37
j  org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(Ljava/lang/reflect/Method;Ljava/lang/Class;Lorg/springframework/transaction/interceptor/TransactionAspectSupport$InvocationCallback;)Ljava/lang/Object;+49
j  org.springframework.transaction.interceptor.TransactionInterceptor.invoke(Lorg/aopalliance/intercept/MethodInvocation;)Ljava/lang/Object;+40
J 1449 C2 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()Ljava/lang/Object; (107 bytes) @ 0x74187c50 [0x74187b90+0xc0]
j  org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(Lorg/aopalliance/intercept/MethodInvocation;)Ljava/lang/Object;+1
J 1449 C2 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()Ljava/lang/Object; (107 bytes) @ 0x74187c50 [0x74187b90+0xc0]
j  org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(Lorg/aopalliance/intercept/MethodInvocation;)Ljava/lang/Object;+89
J 1449 C2 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()Ljava/lang/Object; (107 bytes) @ 0x74187c50 [0x74187b90+0xc0]
j  org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(Lorg/aopalliance/intercept/MethodInvocation;)Ljava/lang/Object;+18
J 1449 C2 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()Ljava/lang/Object; (107 bytes) @ 0x74187c50 [0x74187b90+0xc0]
j  org.springframework.aop.framework.JdkDynamicAopProxy.invoke(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;+321
j  com.sun.proxy.$Proxy67.save(Ljava/lang/Object;)Ljava/lang/Object;+16
j  ro.i2cWebAppController.app.serv.BaseServiceImpl.save(Lro/i2cWebAppController/app/model/BaseModel;)Lro/i2cWebAppController/app/model/BaseModel;+5
j  ro.i2cWebAppController.app.schedule.RaspberryPiScheduler.writeRaspberryPiData()V+116
j  sun.reflect.GeneratedMethodAccessor64.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+36
J 580 C2 java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; (62 bytes) @ 0x73ffafac [0x73ffaf10+0x9c]
j  org.springframework.scheduling.support.ScheduledMethodRunnable.run()V+19
j  org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run()V+4
j  java.util.concurrent.Executors$RunnableAdapter.call()Ljava/lang/Object;+4
j  java.util.concurrent.FutureTask.runAndReset()Z+47
j  java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Ljava/util/concurrent/ScheduledThreadPoolExecutor$ScheduledFutureTask;)Z+1
j  java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run()V+37
j  java.util.concurrent.ThreadPoolExecutor.runWorker(Ljava/util/concurrent/ThreadPoolExecutor$Worker;)V+95
j  java.util.concurrent.ThreadPoolExecutor$Worker.run()V+5
j  java.lang.Thread.run()V+11
v  ~StubRoutines::call_stub
C  0x609aed68

And i found a very strange behaviour. 我发现了一个非常奇怪的行为。 After following the advices from comments, i added the following lines in tomcat starting script : 在遵循注释的建议后,我在tomcat启动脚本中添加了以下几行:

Environment='CATALINA_OPTS=-Xms64M -Xmx192M -server -XX:+UseParallelGC -XX:+UnlockCommercialFeatures -XX:+FlightRecorder'
Environment='JAVA_OPTS=-Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom -Dcom.sun.management.jmxremote.port=7091 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false'

and i connected Java Mission Control and Flight Recording to raspberry's JVM. 我将Java Mission Control和Flight Recording连接到了树莓派的JVM。 The strange thing is that the JVM didn't crash after 12 hours of monitoring, everything was working ok. 奇怪的是,经过12个小时的监视,JVM并未崩溃,一切正常。 After restarting the server with "XX:+UnlockCommercialFeatures -XX:+FlightRecorder" and "-Dcom.sun.management.jmxremote.port=7091 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false" removerd, JVM crashed after 7 hours. 使用“ XX:+ UnlockCommercialFeatures -XX:+ FlightRecorder”和“ -Dcom.sun.management.jmxremote.port = 7091 -Dcom.sun.management.jmxremote.authenticate = false -Dcom.sun.management.jmxremote重新启动服务器后.ssl = false“ removerd,JVM在7小时后崩溃。

And with Mission Control and Flight Recording connected to JVM i also noticed that Committed Heap is allways rising but never dropping. 通过将任务控制和飞行记录连接到JVM,我还注意到Committed Heap一直在增加,但从未下降。

Java memory Heap Diagram Java内存堆图

Problem solved after Java update from 1.8.0 to 1.8.0_65. Java从1.8.0更新到1.8.0_65后解决的问题。

Thank you for tips. 感谢您的提示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM