Java Heap Size Exception

Problem

I was getting this error after setting up a new instance of Tomcat7, using Java 1.7 and running OpenMRS2:

Exception in thread “ActiveMQ Journal Checkpoint Worker” java.lang.OutOfMemoryError: Java heap space
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.getDeclaredMethod(Class.java:2128)
at java.io.ObjectStreamClass.getInheritableMethod(ObjectStreamClass.java:1442)
Exception in thread “ActiveMQ Broker[localhost] Scheduler” at java.io.ObjectStreamClass.access$2200(ObjectStreamClass.java:72)
at java.io.ObjectStreamClass$2.run(ObjectStreamClass.java:510)
at java.io.ObjectStreamClass$2.run(ObjectStreamClass.java:472)
at java.security.AccessController.doPrivileged(Native Method)
at java.io.ObjectStreamClass.<init>(ObjectStreamClass.java:472)
at java.io.ObjectStreamClass.lookup(ObjectStreamClass.java:369)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1134)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at org.apache.activemq.store.kahadb.MessageDatabase.checkpointProducerAudit(MessageDatabase.java:1250)
at org.apache.activemq.store.kahadb.MessageDatabase.checkpointUpdate(MessageDatabase.java:1134)
at org.apache.activemq.store.kahadb.MessageDatabase$10.execute(MessageDatabase.java:698)
at org.apache.kahadb.page.Transaction.execute(Transaction.java:728)
at org.apache.activemq.store.kahadb.MessageDatabase.checkpointCleanup(MessageDatabase.java:696)
at org.apache.activemq.store.kahadb.MessageDatabase$3.run(MessageDatabase.java:293)
java.lang.OutOfMemoryError: Java heap space
at java.util.HashMap.newNode(HashMap.java:1734)
at java.util.HashMap.putVal(HashMap.java:630)
at java.util.HashMap.putMapEntries(HashMap.java:514)
at java.util.HashMap.<init>(HashMap.java:489)
at org.apache.activemq.broker.region.AbstractRegion.getDestinationMap(AbstractRegion.java:223)
at org.apache.activemq.broker.region.RegionBroker.getDestinationMap(RegionBroker.java:134)
at org.apache.activemq.broker.region.RegionBroker.purgeInactiveDestinations(RegionBroker.java:922)
at org.apache.activemq.broker.region.RegionBroker$1.run(RegionBroker.java:110)
at org.apache.activemq.thread.SchedulerTimerTask.run(SchedulerTimerTask.java:33)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)

A Java Heap Size error occurs because of certain memory intensive actions (like Data Exporting). The new Spring managed API uses a lot of memory to cache the xml beans. You may need to increase the default memory allocation.

Solution

According to this wiki page, the solution was to adjust the memory settings. Depending on your OS, I was using Ubuntu 16.04.1 LTS.

vim /etc/default/tomcat7

Then change the JAVA_OPTS variable to:

JAVA_OPTS=”-Djava.awt.headless=true -Xmx1024M -Xms1024M -XX:PermSize=256m -XX:MaxPermSize=256m -XX:NewSize=128m”

You can adjust the memory as per your needs, in my case this was multiplying everything by 2:

JAVA_OPTS=”-Djava.awt.headless=true -Xmx2048M -Xms2048M -XX:PermSize=512m -XX:MaxPermSize=512m -XX:NewSize=256m”

Resources

Troubleshooting Memory Errors

Java heap space errors when starting a new installation

Configure Priority of Process Startup Linux

Problem

I had an application that is dependent on another, starting up at the same time as the other application. One potential solution was to add a wait/sleep timer to the startup script but this would slow up booting or add unnecessary wait time when the application needed to be restarted without server reboot.

Solution

Change the boot sequence of the application that is dependent on the other, making it start up much later than the rest. This is well explained here.

Ubuntu still uses init scripts and that are symlinked to different runlevels. Therefore:

  • Check the current boot sequence. This will give you a long list, you can filter it further to see the actual startup script you are looking for:
root@server:/home/user# ls /etc/rc*/
  • Remove the current scripts:
root@server:/home/user# update-rc.d -f source remove
Removing any system startup links for /etc/init.d/source ...
/etc/rc0.d/K20source
/etc/rc1.d/K20source
/etc/rc2.d/S20source
/etc/rc3.d/S20source
/etc/rc4.d/S20source
/etc/rc5.d/S20source
/etc/rc6.d/K20source
root@server:/home/user# update-rc.d source start 95 2 3 4 5 . stop 05 S 0 1 6 .
Adding system startup for /etc/init.d/source ...
/etc/rc0.d/K05source -> ../init.d/source
/etc/rc1.d/K05source -> ../init.d/source
/etc/rc6.d/K05source -> ../init.d/source
/etc/rcS.d/K05source -> ../init.d/source
/etc/rc2.d/S95source -> ../init.d/source
/etc/rc3.d/S95source -> ../init.d/source
/etc/rc4.d/S95source -> ../init.d/source
/etc/rc5.d/S95source -> ../init.d/source

Finally restart your server and see if this was successful.

Resources

What’s the connection between “/etc/init.d” and “/etc/rcX.d” directories in Linux?

How to Delay A Startup Service?

update-rc.d command warning

UbuntuBootupHowto

upstart Getting Started

Ubuntu’s Upstart event-based init daemon

custom service start at boot

UpstartHowtoUpstart Intro, Cookbook and Best Practises

update-rc.d ignoring my init script’s runlevels

MySQL Strip Time from Timestamp Columns

Problem

I needed a way to be able to only use the date part of a timestamp column in the WHERE clause without having to introduce another element such as formatting.

Solution

Solution was to use BETWEEN and then CAST the start and end dates as date as explained in this post.

For instance:

SELECT * FROM testdata WHERE current_date BETWEEN CAST(start_date as DATE) and CAST(end_date as DATE);

Side notes,

CURDATE() Returns the current date as a value in 'YYYY-MM-DD' or YYYYMMDD format, depending on whether the function is used in a string or numeric context.

Use IFNULL() to check if a returns a null and replace the null with something e.g blank:

IFNULL(personname.given_name,”) as GivenName

Resource:

SQL between dates including start and end dates

How to check if field is null or empty mysql?

How do I check if a column is empty or null in mysql

Working with NULL Values

Tomcat URL Redirect

Problem

Needed to re-direct a user to the default Tomcat web app when they select the base URL

Solution

Simple solution was to add the following line:

<% response.sendRedirect("/nameofyourwebapp"); %>

to the index.jsp page in /usr/local/tomcat/webapps/ROOT.

Therefore your top section of the default Tomcat index.jsp will now probably look like this:

<!DOCTYPE html>
<% response.sendRedirect("/nameofyourwebapp"); %>
<%@ page session="false" %>
<%
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy");
request.setAttribute("year", sdf.format(new java.util.Date()));
request.setAttribute("tomcatUrl", "http://tomcat.apache.org/");
request.setAttribute("tomcatDocUrl", "/docs/");
request.setAttribute("tomcatExamplesUrl", "/examples/");
%>

The best solution would be to use UrlRewriteFilter I havent tested this out yet though. The above was simple enough for my needs.

Resources

Tomcat base URL redirection

UrlRewriteFilter

UrlRewriteFilter 4.0.3

301 permanent redirect with Tomcat HOWTO

How do I override the default home page loaded by Tomcat?

Ubuntu Install Only Certain Updates

Problem

Needed a way to choose which updates to install.

Solution

apt-get update — To check what’s new

apt-get upgrade — To update installed packages without kernel modules

apt-get dist-upgrade — To install all updates for installed packages with kernel modules

apt-get -s dist-upgrade — To simulate the above without making any changes.

apt-get install –only-upgrade [package_name] e.g

apt-get install –only-upgrade liboxideqt-qmlplugin — To only upgrade one specific package and not all (This is useful if you first run the simulate dist upgrade command above)

Resources

How can I install just security updates from the command line?

How to install updates via command line?

How to upgrade a single package using apt-get?

Duplicate Sources.list Entry Chrome

Problem

I was getting the following error when updating ubuntu 14.04 on Linux Mint 17.02:


W: Duplicate sources.list entry http://dl.google.com/linux/chrome/deb/ stable/main amd64 Packages (/var/lib/apt/lists/dl.google.com_linux_chrome_deb_dists_stable_main_b
inary-amd64_Packages)
W: Duplicate sources.list entry http://dl.google.com/linux/chrome/deb/ stable/main i386 Packages (/var/lib/apt/lists/dl.google.com_linux_chrome_deb_dists_stable_main_bi
nary-i386_Packages)
W: You may want to run apt-get update to correct these problems

Solution

First I had to remove the duplicate Google Source Entry by going to Software Sources -> Additional repositories:

Linux Mint 17.2 Source Sources
Linux Mint 17.2 Source Sources

Then From there check that the 2 Google Repositories have the same repo:

Check Google Additional and Google Chrome List repositories
Check Google Additional and Google Chrome List repositories

After confirming the above, I unchecked the Google additional repositories entry and clicked on Update Cache:

Uncheck Extra Google Repo and Click on Update the cache
Uncheck Extra Google Repo and Click on Update the cache

I got another error after clicking update the cache:


Failed to fetch http://dl.google.com/linux/chrome/deb/dists/stable/Release Unable to find expected entry 'main/binary-i386/Packages' in Release file (Wrong sources.list entry or malformed file)
Some index files failed to download. They have been ignored, or old ones used instead.

From this post 32-bit builds of Google Chrome have been discontinued. Therefore quick fix was to switch to the 64bit Only Repo by adding  [arch=amd64]. This can be done quickly by:

theone# sudo sed -i -e ‘s/deb http/deb [arch=amd64] http/’ “/etc/apt/sources.list.d/google-chrome.list”
theone # sudo sed -i -e ‘s/deb http/deb [arch=amd64] http/’ “/opt/google/chrome/cron/google-chrome”
theone # cat /etc/apt/sources.list.d/google-chrome.list
### THIS FILE IS AUTOMATICALLY CONFIGURED ###
# You may comment out this entry, but any other modifications may be lost.
deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main

After this running apt-get update should not throw any errors:

References

How To Fix Failed To Fetch http://dl.google.com/linux/chrome/deb/dists/stable/Release on Ubuntu 14.04

Solved W: Duplicate sources.list entry Ubuntu 13.04 12.10 12.04

How to fix Duplicate sources.list entry?

 

 

Creating Multiple webapps on Tomcat

Problem

Needed to ran 2 applications deployed using war(s) on Tomcat but use different application directories as well as URLs.

Solution

Stop Tomcat

copy the war into the WEBAPPS directory. Ensure that the war has a different name from the other war e.g application2.war

Start Tomcat

Tomcat will deploy the war and create a directory called application2 in the WEBAPPS directory.

Stop tomcat

Go to the WEBAPPS directory and open the application2/WEB-INF/server directory and:

  • Add the application2 directory in the context param under (<!– These init parameter(s) are read in by org.xxxx.web.Listener –>)
# pwd
/var/lib/tomcat7/webapps
# vim application2/WEB-INF/web.xml

<context-param>
<param-name>application.data.directory</param-name>
<param-value>/usr/share/tomcat7/.application2/</param-value>
</context-param>
<!-- // End init parameters -->
  • Add the webAppRootKey context param after (<!– // End init parameters –>)
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>openmrs-marira</param-value>
</context-param>
  • Now you can restart Tomcat and you should be apply to access application one under URL http://localhost:8080/application1 and application2 under URL http://localhost:8080/application2

Fill in Missing Dates – Using MySQL

Problem

Had a report that only displayed dates in a calendar month for which there was data. I needed a way to add Zero(s) for the missing days:

Original and final report looked like this:

Selection_140
Original Report
Using Mysql to fill in dates missing in a report
Edited Report with missing days

 

 

Solution

Create a table with dates and then left join this to the other table with missing dates. Instructions on how to create this table called calendar are from this post.

Create a table Calendar:

CREATE TABLE calendar (datefield DATE) 

Create a stored procedure that will be used to fill in the dates:

DELIMITER |
CREATE PROCEDURE fill_calendar(start_date DATE, end_date DATE)
BEGIN
 DECLARE crt_date DATE;
 SET crt_date=start_date;
 WHILE crt_date &lt; end_date DO
 INSERT INTO calendar VALUES(crt_date);
 SET crt_date = ADDDATE(crt_date, INTERVAL 1 DAY);
 END WHILE;
END |
DELIMITER ; 

To fill in the dates enter start date and end date as per the below:

CALL fill_calendar('2008-01-01', '2011-12-31'); 

Note that if your date range is too long the server might timeout your query at some point. Just order by date descending to see the last date inserted and add more if necessary.

Then left join this table with your data:

SELECT
calendar.datefield as calendar,
coalesce(Diagnosis_Table.name,'No Diagnosis') as diagnosis,
coalesce(PatientVisit_Table.diagnosiscode,NULL) AS NoOfDiagnosis
FROM
calendar
LEFT JOIN PatientVisit_Table on DATE(PatientVisit_Table.datetime) = calendar.datefield
AND PatientVisit_Table.diagnosiscode NOT IN ('restricteddiagnosislist)
LEFT JOIN Diagnosis_Table ON PatientVisit_Table.diagnosiscode = Diagnosis_Table.id

WHERE
(calendar.datefield BETWEEN $P{beginDate} AND $P{endDate} )

NOTE: I’ve edited the query abit but you get the gist of what’s happening. You can join many more tables as per your needs. Also note, in my case the filled in dates from the calendar table were being removed (meaning I was back to only getting results of dates with data) when I place conditions such as [PatientVisit_Table.diagnosiscode NOT IN (‘restricteddiagnosislist)] in the WHERE clause.

SO I had to move these conditions to the join statement, I believe this is called using a composite key 

References

Using MySQL to generate daily sales reports with filled gaps

MySQL how to fill missing dates in range?

Filling in missing data with sequences of cardinal integers

using join to merge files

Printing days of the month

Group by day with filled gaps

MYSQL fill group by “gaps”

iReport Group with Date and Incrementing Date? iReport Group with Date and Incrementing Date?

MySQL Query – Include dates without records

MySQL DATE_ADD() Function

Recipe9.10.Filling in Missing Dates

ON clause condition versus WHERE clause condition WITH JOIN in mysql

MySQL join with where clause

An Introduction to MySQL Views

MySQL Tutorial 2: Views and Joins

Creating Views in MySQL