A Termux-compatible JNI implementation of file watching functionality for the Kotlin Language Server. This library provides both stub and real implementations to solve glibc compatibility issues when running IntelliJ-based language servers on Android/Termux.
The original Kotlin LSP includes a native library libfilewatcher_jni.so
compiled for glibc-based Linux systems. On Termux (Android), this causes UnsatisfiedLinkError
due to:
- ABI Incompatibility: glibc vs Android's Bionic libc
- Missing Symbol Versions: Different C library implementations
- Dependency Chain Issues: Even symlinks don't resolve ABI differences
This project provides drop-in replacements that work natively on Termux while maintaining full API compatibility.
- β Quick Fix: Resolves loading errors immediately
- β Zero Dependencies: No additional system requirements
- β Minimal Overhead: ~4KB library size
- β No File Watching: LSP won't detect external file changes
- β Full File Monitoring: Complete inotify-based file watching
- β High Performance: Kernel-level event notification (~100x faster than polling)
- β Thread Safe: Proper synchronization for multi-threaded LSP servers
- β Event Types: CREATE, MODIFY, DELETE, OVERFLOW support
- β Memory Efficient: ~20KB library + ~1KB per watcher
pkg install clang openjdk-17
If you're unsure of your architecture:
# Check your architecture
uname -m
# aarch64 -> use libfilewatcher-aarch64-*.tar.gz
# armv7l -> use libfilewatcher-arm-*.tar.gz
# x86_64 -> use libfilewatcher-x86_64-*.tar.gz
# i686 -> use libfilewatcher-i686-*.tar.gz
# Download specific version for your architecture
wget https://github.com/yamsergey/termux-filewatcher/releases/download/v1.0.0/libfilewatcher-aarch64-v1.0.0.tar.gz
tar -xzf libfilewatcher-aarch64-v1.0.0.tar.gz
cp libfilewatcher_jni.so /path/to/kotlin-lsp/native/Linux-AArch64/
# Clone the repository
git clone https://github.com/yamsergey/termux-filewatcher.git
cd termux-filewatcher
# Build the library (real implementation by default)
make
# Or build stub implementation
make stub
# Install to Kotlin LSP
make install KOTLIN_LSP_PATH=/path/to/kotlin-lsp
## π Usage
Once installed, the Kotlin LSP will use the new native library automatically:
```bash
# Start LSP server
./kotlin-lsp.sh.orig --stdio
import com.jetbrains.analyzer.filewatcher.FileWatcher;
public class TestFileWatcher {
public static void main(String[] args) throws Exception {
FileWatcher watcher = new FileWatcher();
watcher.watch("/tmp");
System.out.println("Watching /tmp - create files to see events...");
// Poll for events
for (int i = 0; i < 10; i++) {
FileWatcher.Event event = watcher.nextEvent();
if (event != null) {
System.out.println("Event: " + event.getKind() + " - " + event.getPath());
}
Thread.sleep(1000);
}
watcher.stop();
}
}
make # Build real implementation
make stub # Build stub implementation
make test # Run test suite
make clean # Clean build artifacts
make install # Install to Kotlin LSP
make uninstall # Restore original library
make docker-test # Test in isolated environment
mkdir build && cd build
cmake ..
make
ctest # Run tests
# Run full test suite
make test
# Run specific test categories
make test-unit # Unit tests only
make test-integration # Integration tests only
make test-performance # Performance benchmarks
# Compile test program
make test-manual
# Test basic functionality
./test/manual/test_basic
# Test performance
./test/manual/test_performance
# Test concurrent access
./test/manual/test_concurrent
Metric | Stub | Real | Original |
---|---|---|---|
Library Size | 4KB | 20KB | 45KB |
Memory per Watcher | 0KB | ~1KB | ~2KB |
Event Latency | N/A | <1ms | N/A |
CPU Usage | Minimal | Low | N/A |
Startup Time | <1ms | <5ms | Crash |
- File Creation: ~0.5ms average latency
- File Modification: ~0.3ms average latency
- File Deletion: ~0.4ms average latency
- Throughput: >1000 events/second sustained
βββββββββββββββββββββββ ββββββββββββββββββββββββ
β Kotlin LSP β β Android/Termux β
β β β β
β βββββββββββββββββββ β β βββββββββββββββββββ β
β β FileWatcher ββββββββ€βΊβ libfilewatcher β β
β β Java Class β β β β JNI Library β β
β βββββββββββββββββββ β β βββββββββββββββββββ β
β β β β β
β βββββββββββββββββββ β β ββββββββββΌβββββββββ β
β β Event Objects ββββββββ€βΊβ Linux inotify β β
β β (CRUD events) β β β β Kernel API β β
β βββββββββββββββββββ β β βββββββββββββββββββ β
βββββββββββββββββββββββ ββββββββββββββββββββββββ
- JNI Interface Layer: Bridges Java FileWatcher to native code
- Event Translation: Converts inotify events to Java Event objects
- Thread Management: pthread-based synchronization
- Memory Management: Global reference caching for performance
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
# Fork and clone
git clone https://github.com/yourusername/termux-filewatcher.git
cd termux-filewatcher
# Install development dependencies
pkg install clang cmake make git
# Run development build
make dev
# Run tests
make test
This project uses tag-based releases. To create a new release:
# Tag the release (use semantic versioning)
git tag v1.0.0
git push --tags
# This automatically triggers GitHub Actions to:
# - Cross-compile for all architectures
# - Create individual architecture archives
# - Publish GitHub release with artifacts
Release artifacts created:
libfilewatcher-aarch64-v1.0.0.tar.gz
libfilewatcher-arm-v1.0.0.tar.gz
libfilewatcher-x86_64-v1.0.0.tar.gz
libfilewatcher-i686-v1.0.0.tar.gz
- C Code: Follow Linux kernel coding style
- Comments: Document all public APIs and complex logic
- Testing: Add tests for all new functionality
- Performance: Benchmark critical paths
# Check file exists and has correct permissions
ls -la /path/to/kotlin-lsp/native/Linux-AArch64/libfilewatcher_jni.so
chmod 755 /path/to/kotlin-lsp/native/Linux-AArch64/libfilewatcher_jni.so
# Ensure required packages are installed
pkg install clang openjdk-17
# Set JAVA_HOME if not set
export JAVA_HOME=$PREFIX/opt/openjdk
# Check inotify limits
cat /proc/sys/fs/inotify/max_user_watches
# Increase if needed (requires root)
echo 65536 > /proc/sys/fs/inotify/max_user_watches
# Build with debug symbols
make debug
# Enable verbose logging
export FILEWATCHER_DEBUG=1
./kotlin-lsp.sh.orig --stdio
This project is licensed under the GNU Lesser General Public License v3.0 - see the LICENSE file for details.
- Kotlin LSP Team - For the original language server implementation
- Termux Project - For making Linux development possible on Android
- inotify Developers - For the efficient file monitoring API
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Wiki: Project Wiki
β If this project helped you, please consider giving it a star!