OpenJDK on AWS with Support by cloudimg User Guide
Overview
The OpenJDK on AWS AMI by cloudimg provides a fully preconfigured OpenJDK (Open Java Development Kit) installation ready to run on Amazon EC2. OpenJDK is the official open source reference implementation of the Java Platform, Standard Edition (Java SE), providing the Java Runtime Environment (JRE), the Java compiler (javac), and the complete set of Java development tools needed to build, test, and run Java applications.
This AMI is designed for developers and operations teams who need a clean, supported Java environment on AWS without the overhead of manual installation and configuration. OpenJDK is installed at /usr/java and is automatically updated on first boot to ensure you are running the latest available version from the system package repositories.
Whether you are running Java application servers, building microservices, executing batch processing jobs, or developing Java applications, this AMI provides a solid foundation with cloudimg's 24/7 support backing.
Visit www.cloudimg.co.uk to explore the full catalogue of preconfigured AMIs available on the AWS Marketplace.
Prerequisites
Before launching the OpenJDK AMI, ensure you have the following in place.
AWS Account You need an active AWS account with permissions to launch EC2 instances and manage security groups.
EC2 Key Pair Create or select an existing EC2 key pair in the region where you plan to launch the instance. This key pair is required for SSH authentication.
Security Group Configuration Your security group must allow inbound traffic on the following ports:
| Protocol | Type | Port | Description |
|---|---|---|---|
| SSH | TCP | 22 | SSH connectivity for remote administration |
If you plan to run a Java application that listens on additional ports (such as a web server on port 8080 or an API on a custom port), add those ports to your security group as needed.
Restrict SSH access to your own IP address or a trusted CIDR range.
Minimum System Requirements
| Minimum CPU | Minimum RAM | Required Disk Space |
|---|---|---|
| 1 vCPU | 1 GB | 20 GB |
For Java applications with significant memory requirements, choose an instance type with sufficient RAM. The JVM heap size is typically configured to use a portion of available system memory, so plan accordingly based on your application's needs.
Step by Step Setup
Step 1: Launch the Instance
- Open the AWS Marketplace listing for OpenJDK on AWS by cloudimg.
- Click Continue to Subscribe, then Continue to Configuration.
- Select your preferred AWS Region and instance type.
- On the launch page, choose your VPC, subnet, and assign the security group you prepared above.
- Select your EC2 key pair and launch the instance.
Step 2: Wait for Status Checks
Allow the EC2 instance to reach 2/2 status checks passed before attempting to connect. The instance runs an initial boot update script that applies the latest operating system patches and ensures OpenJDK is up to date, so the first boot may take a few minutes longer than usual.
If you attempt to connect before both status checks have passed, you may see errors such as:
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
ec2-user@your-instance-ip's password:
This is expected behaviour during early boot. Wait for the status checks to complete and try again.
Step 3: Connect via SSH
Connect to the instance using your private key:
ssh -i /path/to/your-key.pem ec2-user@<PUBLIC_IP>
Replace <PUBLIC_IP> with the public IP address or public DNS name shown in the EC2 console.
Step 4: Switch to the Root User
Once connected as ec2-user, switch to the root user for administrative tasks:
sudo su -
Step 5: Verify the Java Installation
Check the installed Java version:
java -version
This will display the OpenJDK version, runtime environment, and VM details. The version may be newer than expected if the initial boot update script installed a more recent release.
Step 6: Verify the Java Compiler
Confirm the Java compiler is available:
javac -version
This verifies that the full JDK (not just the JRE) is installed and ready for compiling Java source code.
Step 7: Check JAVA_HOME
Verify the JAVA_HOME environment variable is set:
echo $JAVA_HOME
If JAVA_HOME is not set in your shell session, you can set it manually:
export JAVA_HOME=/usr/java
To make this permanent, add the export line to your shell profile file (~/.bashrc or ~/.bash_profile).
Server Components
The OpenJDK AMI includes the following preconfigured component.
| Component | Software Home | Description |
|---|---|---|
| OpenJDK | /usr/java | Open source Java Development Kit including JRE, compiler, and development tools |
The OpenJDK installation includes: - java command for running Java applications - javac compiler for compiling Java source code - jar tool for creating and managing JAR archives - jdb debugger for debugging Java programs - javadoc tool for generating API documentation - keytool for managing cryptographic keys and certificates - jps for listing running Java processes - jstack for printing Java thread stack traces - jmap for printing memory maps of Java processes - jstat for monitoring JVM statistics
Filesystem Layout
The AMI uses a straightforward filesystem layout with the operating system and Java installed on the root volume.
| Mount Point | Description |
|---|---|
| / | Root filesystem containing the operating system and all software |
| /boot | Operating system kernel files |
Key directories and their purposes:
| Path | Purpose |
|---|---|
| /usr/java | OpenJDK installation directory (JAVA_HOME) |
| /usr/java/bin | Java binaries including java, javac, jar, and other tools |
| /usr/java/lib | Java libraries and runtime support files |
| /usr/java/conf | Java configuration files including security settings |
| /usr/java/include | C header files for the Java Native Interface (JNI) |
| /stage/scripts | cloudimg provisioning scripts and log files |
Managing Services
OpenJDK itself is not a service but a development platform and runtime. Java applications that you deploy on this instance may be run as services or background processes.
Running a Java Application
java -jar /path/to/your-application.jar
Running a Java Application in the Background
nohup java -jar /path/to/your-application.jar > /var/log/myapp.log 2>&1 &
Running a Java Application as a Systemd Service
For production deployments, create a systemd service unit to manage your Java application:
cat > /etc/systemd/system/myapp.service << 'EOF'
[Unit]
Description=My Java Application
After=network.target
[Service]
Type=simple
User=ec2-user
ExecStart=/usr/java/bin/java -jar /opt/myapp/application.jar
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
Enable and start the service:
systemctl daemon-reload
systemctl enable myapp
systemctl start myapp
Manage the service:
# Check status
systemctl status myapp
# Stop the service
systemctl stop myapp
# Restart the service
systemctl restart myapp
# View logs
journalctl -u myapp -f
Scripts and Log Files
The AMI includes the following scripts and log files created by cloudimg.
| Script or Log | Path | Description |
|---|---|---|
| initial_boot_update.sh | /stage/scripts | Updates the operating system with the latest available patches on first boot |
| initial_boot_update.log | /stage/scripts | Output log from the initial boot update script |
Disabling the Initial Boot Update Script
The OS update script runs automatically on every reboot via crontab. If you prefer to manage updates manually, you can disable it:
rm -f /stage/scripts/initial_boot_update.sh
crontab -e
# DELETE THE BELOW LINE, SAVE AND EXIT THE FILE:
@reboot /stage/scripts/initial_boot_update.sh
Common Java Operations
Compiling and Running a Java Program
Create a simple Java file to test the installation:
cat > HelloWorld.java << 'EOF'
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello from OpenJDK on AWS!");
}
}
EOF
javac HelloWorld.java
java HelloWorld
Checking Available Java Alternatives
If multiple Java versions are installed, you can switch between them:
alternatives --config java
Setting JVM Memory Options
When running Java applications, configure the heap size based on your instance's available memory:
# Set initial and maximum heap to 2GB
java -Xms2g -Xmx2g -jar application.jar
# Set heap as a percentage of available RAM (Java 10+)
java -XX:MaxRAMPercentage=75.0 -jar application.jar
Creating a JAR File
# Compile source files
javac -d build src/*.java
# Create a JAR archive
jar cf myapp.jar -C build .
# Create an executable JAR with a manifest
jar cfe myapp.jar com.example.Main -C build .
Monitoring Java Processes
# List running Java processes
jps -lv
# Show thread dump for a Java process
jstack <PID>
# Show heap usage summary
jmap -heap <PID>
# Monitor JVM statistics
jstat -gc <PID> 1000
Working with Build Tools
This AMI provides a clean Java environment that you can extend with build tools as needed.
Installing Apache Maven
cd /opt
wget https://dlcdn.apache.org/maven/maven-3/3.9.6/binaries/apache-maven-3.9.6-bin.tar.gz
tar xzf apache-maven-3.9.6-bin.tar.gz
ln -s apache-maven-3.9.6 maven
echo 'export M2_HOME=/opt/maven' >> /etc/profile.d/maven.sh
echo 'export PATH=$M2_HOME/bin:$PATH' >> /etc/profile.d/maven.sh
source /etc/profile.d/maven.sh
mvn --version
Installing Gradle
cd /opt
wget https://services.gradle.org/distributions/gradle-8.5-bin.zip
unzip gradle-8.5-bin.zip
ln -s gradle-8.5 gradle
echo 'export GRADLE_HOME=/opt/gradle' >> /etc/profile.d/gradle.sh
echo 'export PATH=$GRADLE_HOME/bin:$PATH' >> /etc/profile.d/gradle.sh
source /etc/profile.d/gradle.sh
gradle --version
Troubleshooting
Cannot connect via SSH
- Confirm the instance has reached 2/2 status checks in the EC2 console.
- Verify your security group allows inbound TCP traffic on port 22 from your IP address.
- Ensure you are using the correct key pair and connecting as
ec2-user. - Check that the key file permissions are set correctly:
chmod 400 /path/to/your-key.pem.
Java command not found
- Verify OpenJDK is installed:
ls -la /usr/java. - Check if the Java binary is on the PATH:
which java. - If not on the PATH, add it manually:
export PATH=/usr/java/bin:$PATH. - The initial boot update may have changed the Java installation location. Check alternatives:
alternatives --config java.
JAVA_HOME is not set
- Set JAVA_HOME manually:
export JAVA_HOME=/usr/java. - To make it permanent, add to
/etc/profile.d/java.sh:echo 'export JAVA_HOME=/usr/java' > /etc/profile.d/java.sh echo 'export PATH=$JAVA_HOME/bin:$PATH' >> /etc/profile.d/java.sh source /etc/profile.d/java.sh
Java application runs out of memory
- Increase the JVM heap size:
java -Xmx4g -jar application.jar. - Consider upgrading to an instance type with more RAM.
- Monitor memory usage with
jstat -gc <PID> 1000orjmap -heap <PID>. - Check for memory leaks using heap dump analysis:
jmap -dump:format=b,file=heap.hprof <PID>.
Java application fails to bind to a port
- Check if the port is already in use:
netstat -tlnp | grep <PORT>. - Ensure the application is not trying to bind to a privileged port (below 1024) without root permissions.
- Verify the security group allows inbound traffic on the port your application uses.
Initial boot update is taking a long time
- The first boot runs a full OS update which can take several minutes.
- Monitor progress:
tail -f /stage/scripts/initial_boot_update.log.
Security Recommendations
Keep Java Updated
Regularly update OpenJDK to receive the latest security patches:
yum update java* -y
Alternatively, keep the initial boot update script enabled to automatically apply updates on reboot.
Restrict SSH Access
Limit SSH (port 22) to specific trusted IP addresses in your security group. Consider using AWS Systems Manager Session Manager as an alternative to direct SSH access.
Apply Operating System Updates
Keep the full operating system up to date:
yum update -y
Run Java Applications as Non Root Users
Never run production Java applications as the root user. Create a dedicated service account:
useradd -r -s /sbin/nologin myappuser
chown -R myappuser:myappuser /opt/myapp
Use systemd service units (as shown in the Managing Services section) to run applications under the dedicated user.
Configure Java Security Settings
Review and configure Java security settings in /usr/java/conf/security/java.security. Key settings include:
- Disabling weak TLS protocols
- Configuring trusted certificate authorities
- Setting secure random number generator algorithms
Use Security Manager for Untrusted Code
If running untrusted or third party Java code, consider using the Java Security Manager to restrict permissions:
java -Djava.security.manager -Djava.security.policy=myapp.policy -jar application.jar
Enable TLS for Network Applications
When your Java application serves network traffic, always configure TLS. Use the keytool command to manage keystores and certificates:
# Generate a self-signed certificate for testing
keytool -genkeypair -alias myapp -keyalg RSA -keysize 2048 -keystore keystore.jks -validity 365
For production, use certificates from a trusted certificate authority.
Monitor and Audit
Enable Java Management Extensions (JMX) monitoring for production applications and integrate with your monitoring infrastructure:
java -Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=9010 \
-Dcom.sun.management.jmxremote.authenticate=true \
-Dcom.sun.management.jmxremote.ssl=true \
-jar application.jar
Backup Your Applications
Use AWS EBS snapshots for volume level backups. For application specific backups, regularly archive your deployment directories and configuration files.
Support
If you encounter any issues not covered in this guide or need further assistance, the cloudimg support team is available 24/7.
Email: support@cloudimg.co.uk Phone: (+44) 02045382725 Website: www.cloudimg.co.uk Address: 3rd Floor, 86 90 Paul Street, London, EC2A 4NE
When contacting support, please include your EC2 instance ID, the AWS region, and a description of the issue along with any relevant log output.