public class IP2LocationService extends Object implements AutoCloseable
This service provides a complete solution for IP geolocation including:
ProxySelector
IP2LocationService service = new IP2LocationService.Builder()
.downloadToken("YOUR_TOKEN")
.database(Database.DB11)
.includeIPv6(true)
.directory(Paths.get("/var/lib/ip2location"))
.build(); // Blocks until databases are loaded
GeoLocation loc = service.lookup("8.8.8.8");
if (loc.isOk()) {
System.out.println("Country: " + loc.getCountryCode());
System.out.println("Location: " + loc.getLocationDescription());
}
// Display service status in UI
statusLabel.setText(service.getStatusDescription());
// "IPv4+IPv6, IPv4 ready, IPv6 ready"
service.dispose();
IP2LocationService service = new IP2LocationService.Builder()
.downloadToken("YOUR_TOKEN")
.database(Database.DB11)
.buildAsync((svc, success, error) -> {
if (success) {
System.out.println("Service ready!");
} else {
System.err.println("Init failed: " + error);
}
});
// Service returned immediately, initialization runs in background
// Wait for initialization if needed:
boolean ready = service.awaitReady(30, TimeUnit.SECONDS);
If the database or state files become corrupted, use recovery mode to clear everything and start fresh:
IP2LocationService service = new IP2LocationService.Builder()
.downloadToken("YOUR_TOKEN")
.database(Database.DB11)
.directory(Paths.get("/var/lib/ip2location"))
.attemptRecovery() // Clears directory before initialization
.build();
For manual recovery without creating a new service:
// Clear directory manually (service must be disposed first!)
Path dir = Paths.get("/var/lib/ip2location");
int deleted = IP2LocationService.clearDirectory(dir, IEventLogger.consoleLogger());
System.out.println("Deleted " + deleted + " files");
The service can be started disabled for environments where geolocation is not needed:
boolean useGeoLocation = Boolean.parseBoolean(
System.getProperty("app.geolocation.enabled", "true"));
IP2LocationService service = new IP2LocationService.Builder()
.downloadToken("YOUR_TOKEN")
.enabled(useGeoLocation) // Disable via configuration
.build();
if (service.isEnabled()) {
GeoLocation loc = service.lookup("8.8.8.8");
}
IP2LocationService service = new IP2LocationService.Builder()
.downloadToken("YOUR_TOKEN")
.threadFactory((task, name, daemon) ->
Thread.ofVirtual().name(name).unstarted(task))
.buildAsync();
IP2Location LITE databases are updated on the 1st of each calendar month. This service follows IP2Location's recommendation to download during days 1-7 of each month. The service also forces a download on startup if the existing database is from a previous month.
When IP2LocationService.Builder.includeIPv6(boolean) is set to true:
The service supports two database access modes:
useMemoryMappedFile=true): Uses less heap memory,
OS manages page caching. Best for production servers with adequate RAM.useMemoryMappedFile=false, default): More predictable
memory behavior. Better for containers or memory-constrained environments.This service is immutable after construction. To change configuration:
dispose() on the existing instanceIP2LocationService.BuilderFor seamless reconfiguration without downtime, use IP2LocationManager.
This class is thread-safe. Multiple threads can safely call lookup(String)
concurrently. Database reloads are performed atomically using read-write locks.
This class now defaults to using a Builder instance with Virtual Threads when running on Java 21 or better.
IP2LocationManager,
Database,
GeoLocation,
IInitializationCallback,
IThreadFactory| Modifier and Type | Class and Description |
|---|---|
static class |
IP2LocationService.Builder
Builder for creating
IP2LocationService instances. |
| Modifier and Type | Method and Description |
|---|---|
boolean |
awaitReady(long timeout,
TimeUnit unit)
Waits for the service to become ready.
|
static int |
clearDirectory(Path directory,
IEventLogger logger)
Clears an IP2Location directory, removing all database and state files.
|
void |
close()
Alias for
dispose() to support try-with-resources. |
void |
dispose()
Disposes of the service, releasing all resources.
|
void |
forceUpdate()
Forces an immediate database update check and download.
|
Database |
getDatabase()
Returns the configured database type.
|
Path |
getDirectory()
Returns the configured storage directory.
|
Throwable |
getInitializationError()
Returns the error that occurred during initialization.
|
LocalDate |
getIPv4DatabaseDate()
Returns the date of the currently loaded IPv4 database.
|
LocalDate |
getIPv6DatabaseDate()
Returns the date of the currently loaded IPv6 database.
|
YearMonth |
getLastUpdateMonth()
Returns the month of the last successful database update.
|
Instant |
getNextScheduledUpdate()
Returns the instant when the next scheduled update check will occur.
|
String |
getStatusDescription()
Returns the current status as a human-readable string for UI display.
|
static boolean |
hasValidDatabases(Path directory,
boolean requireIPv6)
Checks if an IP2Location directory contains valid database files.
|
boolean |
isEnabled()
Returns whether the service is enabled.
|
boolean |
isIPv4Ready()
Returns whether an IPv4 database is loaded and ready.
|
boolean |
isIPv6Enabled()
Returns whether IPv6 support is enabled.
|
boolean |
isIPv6Ready()
Returns whether an IPv6 database is loaded and ready.
|
boolean |
isReady()
Returns whether the service is ready to handle lookups.
|
boolean |
isRunning()
Returns whether the service is currently running.
|
boolean |
isUsingMemoryMappedFile()
Returns whether memory-mapped file mode is enabled.
|
GeoLocation |
lookup(String ip)
Looks up geolocation information for an IP address.
|
void |
setDatabaseLoadCallback(BiConsumer<LocalDate,Boolean> callback)
Sets a callback invoked when a database file is loaded into memory.
|
void |
setDownloadCallback(IInitializationCallback callback)
Sets a callback invoked after each download attempt (forced or scheduled).
|
public static int clearDirectory(Path directory, IEventLogger logger) throws IOException
This is a recovery utility that can be used when the database or state files become corrupted. It deletes:
*.BIN and *.bin database files.ip2location-state.properties)*.tmp temporary files*.zip download filesImportant: All IP2LocationService instances using this directory must be disposed before calling this method. Otherwise, the service may hold file locks that prevent deletion, or may become unstable.
// First, dispose the service
service.dispose();
// Clear the directory
Path dir = Paths.get("/var/lib/ip2location");
int deleted = IP2LocationService.clearDirectory(dir, IEventLogger.consoleLogger());
System.out.println("Deleted " + deleted + " files");
// Create a new service (will download fresh databases)
service = new IP2LocationService.Builder()
.downloadToken("YOUR_TOKEN")
.directory(dir)
.build();
directory - The directory to clearlogger - Logger for reporting progress (may be null for silent operation)IOException - if the directory cannot be accessed or files cannot be deletedpublic static boolean hasValidDatabases(Path directory, boolean requireIPv6)
This method can be used to determine if recovery might be needed before creating a service instance.
directory - The directory to checkrequireIPv6 - Whether to require both IPv4 and IPv6 databasestrue if the directory contains the required database filespublic void dispose()
This method:
After calling this method, the service cannot be restarted. This method is idempotent.
public void close()
dispose() to support try-with-resources.close in interface AutoCloseablepublic boolean isReady()
A service is ready when at least one database has been loaded. This method returns immediately without blocking.
true if at least one database is loadedpublic boolean awaitReady(long timeout,
TimeUnit unit)
throws InterruptedException
Blocks until initialization completes or the timeout expires.
timeout - The maximum time to waitunit - The time unittrue if the service is ready, false if timeout expiredInterruptedException - if the current thread was interruptedpublic Throwable getInitializationError()
null if successfulpublic GeoLocation lookup(String ip)
This method automatically detects whether the IP is IPv4 or IPv6 and routes to the appropriate database.
ip - The IP address to look up (e.g., "8.8.8.8" or "2001:4860:4860::8888")GeoLocation containing the result (check GeoLocation.isOk())public boolean isEnabled()
When disabled, the service does not download or load databases,
does not start the update scheduler, and lookups return
STATUS_SERVICE_DISABLED.
A disabled service consumes minimal resources and can be used as a placeholder when geolocation is not needed in certain environments (e.g., development, testing).
true if the service is enabled, false if disabledIP2LocationService.Builder.enabled(boolean)public boolean isRunning()
true if started and not disposedpublic boolean isIPv4Ready()
true if IPv4 lookups are availablepublic boolean isIPv6Ready()
true if IPv6 lookups are availablepublic YearMonth getLastUpdateMonth()
null if never updatedpublic boolean isUsingMemoryMappedFile()
true if using memory-mapped filespublic Path getDirectory()
public Database getDatabase()
public boolean isIPv6Enabled()
true if IPv6 lookups are enabledpublic LocalDate getIPv4DatabaseDate()
The date reflects when the database was published by IP2Location, typically the 1st of the month.
null if no IPv4 database is loadedpublic LocalDate getIPv6DatabaseDate()
The date reflects when the database was published by IP2Location, typically the 1st of the month.
null if no IPv6 database is loaded
or IPv6 support is not enabledpublic Instant getNextScheduledUpdate()
This reflects the scheduler's next planned execution, not necessarily when a download will occur (which depends on the current month and whether an update is needed).
null if
the scheduler is not running (service disabled, not started,
or disposed)public String getStatusDescription()
The status components are concatenated in order of importance, separated by ", " (comma and space). Possible components include:
nullpublic void setDownloadCallback(IInitializationCallback callback)
callback - The callback, or null to removepublic void setDatabaseLoadCallback(BiConsumer<LocalDate,Boolean> callback)
callback - The callback receiving (date, isIPv6), or null to removepublic void forceUpdate()
This bypasses the normal scheduling logic and attempts to download the latest database immediately. The operation runs asynchronously.
IllegalStateException - if the service is not runningPhantom® and NetPhantom® are registered trademarks of Mindus SARL.
© 2026 Mindus SARL. All rights reserved.