From a6e145cc08b57bd313c89db86fc80e3fbb9eeaa5 Mon Sep 17 00:00:00 2001 From: Antoine Toulme Date: Sun, 2 Aug 2020 22:43:27 -0700 Subject: [PATCH 1/2] Essential fixes for EVMc Java bindings --- bindings/java/Makefile | 3 ++ bindings/java/c/evmc-vm.c | 9 +++++ .../main/java/org/ethereum/evmc/EvmcVm.java | 36 +++++++------------ .../java/org/ethereum/evmc/HostContext.java | 5 +++ .../test/java/org/ethereum/evmc/EvmcTest.java | 27 +++++++------- 5 files changed, 43 insertions(+), 37 deletions(-) diff --git a/bindings/java/Makefile b/bindings/java/Makefile index 666fc6543..ccb9fe9f3 100644 --- a/bindings/java/Makefile +++ b/bindings/java/Makefile @@ -22,6 +22,9 @@ $(OUT_DIR)/lib/libevmc-java.so: mkdir -p $(BUILD_DIR) (cd $(BUILD_DIR) && cmake $(SOURCE_DIR) -DCMAKE_INSTALL_PREFIX=$(OUT_DIR) -DEVMC_JAVA=ON -DJAVA_HOME=$(JAVA_HOME) -DEVMC_EXAMPLES=ON) cmake --build $(OUT_DIR)/_cmake_build --target install + mkdir -p $(CURDIR)/java/src/test/resources + cp $(OUT_DIR)/lib/libevmc-java.so $(CURDIR)/java/src/test/resources/libevmc.so + cp $(OUT_DIR)/lib/libexample-vm.so $(CURDIR)/java/src/test/resources/libexample-vm.so clean: rm -rf $(OUT_DIR) diff --git a/bindings/java/c/evmc-vm.c b/bindings/java/c/evmc-vm.c index 53a8ddfc7..0c0a3507c 100644 --- a/bindings/java/c/evmc-vm.c +++ b/bindings/java/c/evmc-vm.c @@ -131,6 +131,15 @@ JNIEXPORT jint JNICALL Java_org_ethereum_evmc_EvmcVm_set_1option(JNIEnv* jenv, return (jint)option_result; } +JNIEXPORT jlong JNICALL Java_org_ethereum_evmc_EvmcVm_address(JNIEnv* jenv, + jclass jcls, + jobject buf) +{ + (void)jcls; + void* p = (*jenv)->GetDirectBufferAddress(jenv, buf); + return (jlong)p; +} + JNIEXPORT jint JNICALL Java_org_ethereum_evmc_EvmcVm_get_1result_1size(JNIEnv* jenv, jclass jcls) { (void)jenv; diff --git a/bindings/java/java/src/main/java/org/ethereum/evmc/EvmcVm.java b/bindings/java/java/src/main/java/org/ethereum/evmc/EvmcVm.java index 178b9b42c..fc70d662b 100644 --- a/bindings/java/java/src/main/java/org/ethereum/evmc/EvmcVm.java +++ b/bindings/java/java/src/main/java/org/ethereum/evmc/EvmcVm.java @@ -6,7 +6,6 @@ import org.ethereum.evmc.EvmcLoaderException; import java.nio.ByteBuffer; -import java.util.Objects; /** * The Java interface to the evm instance. @@ -14,30 +13,18 @@ *

Defines the Java methods capable of accessing the evm implementation. */ public final class EvmcVm implements AutoCloseable { - private static EvmcVm evmcVm; - private static boolean isEvmcLibraryLoaded = false; private ByteBuffer nativeVm; + /** * This method loads the specified evm shared library and loads/initializes the jni bindings. * + * @param evmcPath the path to the evmc shared library * @param filename /path/filename of the evm shared object * @throws EvmcLoaderException */ - public static EvmcVm create(String filename) throws EvmcLoaderException { - if (!EvmcVm.isEvmcLibraryLoaded) { - try { - // load so containing the jni bindings to evmc - System.load(System.getProperty("user.dir") + "/../c/build/lib/libevmc-java.so"); - EvmcVm.isEvmcLibraryLoaded = true; - } catch (UnsatisfiedLinkError e) { - System.err.println("Native code library failed to load.\n" + e); - System.exit(1); - } - } - if (Objects.isNull(evmcVm)) { - evmcVm = new EvmcVm(filename); - } - return evmcVm; + public static EvmcVm create(String evmcPath, String filename) { + System.load(evmcPath); + return new EvmcVm(filename); } private EvmcVm(String filename) throws EvmcLoaderException { @@ -153,14 +140,15 @@ public int set_option(String name, String value) { private static native int get_result_size(); /** - * This method cleans up resources - * - * @throws Exception + * Utility method to get a bytebuffer address + * @param buffer the byte buffer to consider + * @return the byte buffer address */ + native long address(ByteBuffer buffer); + + /** This method cleans up resources */ @Override - public void close() throws Exception { + public void close() { destroy(nativeVm); - isEvmcLibraryLoaded = false; - evmcVm = null; } } diff --git a/bindings/java/java/src/main/java/org/ethereum/evmc/HostContext.java b/bindings/java/java/src/main/java/org/ethereum/evmc/HostContext.java index 1650a9ae5..70f1ccb1a 100644 --- a/bindings/java/java/src/main/java/org/ethereum/evmc/HostContext.java +++ b/bindings/java/java/src/main/java/org/ethereum/evmc/HostContext.java @@ -145,4 +145,9 @@ public interface HostContext { * @param topicCount The number of the topics. Valid values are between 0 and 4 inclusively. */ void emitLog(byte[] address, byte[] data, int dataSize, byte[][] topics, int topicCount); + + /** + * Closes the context and frees all underlying resources. + */ + default void close() {}; } diff --git a/bindings/java/java/src/test/java/org/ethereum/evmc/EvmcTest.java b/bindings/java/java/src/test/java/org/ethereum/evmc/EvmcTest.java index 6d2053024..714940199 100644 --- a/bindings/java/java/src/test/java/org/ethereum/evmc/EvmcTest.java +++ b/bindings/java/java/src/test/java/org/ethereum/evmc/EvmcTest.java @@ -9,20 +9,21 @@ import org.junit.jupiter.api.Test; final class EvmcTest { + private static final String libEvmcPath = EvmcTest.class.getResource("/libevmc.so").getFile(); private static final String exampleVmPath = - System.getProperty("user.dir") + "/../c/build/lib/libexample-vm.so"; + EvmcTest.class.getResource("/libexample-vm.so").getFile(); @Test void testInitCloseDestroy() throws Exception { Assertions.assertDoesNotThrow( () -> { - try (EvmcVm vm = EvmcVm.create(exampleVmPath)) {} + try (EvmcVm vm = EvmcVm.create(libEvmcPath, exampleVmPath)) {} }); } @Test void testAbiVersion() throws Exception { - try (EvmcVm vm = EvmcVm.create(exampleVmPath)) { + try (EvmcVm vm = EvmcVm.create(libEvmcPath, exampleVmPath)) { int abiVersion = vm.abi_version(); assert (abiVersion > 0); } @@ -30,7 +31,7 @@ void testAbiVersion() throws Exception { @Test void testName() throws Exception { - try (EvmcVm vm = EvmcVm.create(exampleVmPath)) { + try (EvmcVm vm = EvmcVm.create(libEvmcPath, exampleVmPath)) { String name = vm.name(); assert (name.length() > 0); assert (name.equals("example_vm")); @@ -39,7 +40,7 @@ void testName() throws Exception { @Test void testVersion() throws Exception { - try (EvmcVm vm = EvmcVm.create(exampleVmPath)) { + try (EvmcVm vm = EvmcVm.create(libEvmcPath, exampleVmPath)) { String version = vm.version(); assert (version.length() >= 5); } @@ -47,7 +48,7 @@ void testVersion() throws Exception { @Test void testExecute_returnAddress() throws Exception { - try (EvmcVm vm = EvmcVm.create(exampleVmPath)) { + try (EvmcVm vm = EvmcVm.create(libEvmcPath, exampleVmPath)) { HostContext context = new TestHostContext(); int BYZANTIUM = 4; int EVMC_CALL = 0; @@ -77,7 +78,7 @@ void testExecute_returnAddress() throws Exception { /** Tests callbacks: get_storage_fn & set_storage_fn */ @Test void testExecute_counter() throws Exception { - try (EvmcVm vm = EvmcVm.create(exampleVmPath)) { + try (EvmcVm vm = EvmcVm.create(libEvmcPath, exampleVmPath)) { HostContext context = new TestHostContext(); int BYZANTIUM = 4; int EVMC_CALL = 0; @@ -107,7 +108,7 @@ void testExecute_counter() throws Exception { /** Tests callbacks: get_tx_context_fn */ @Test void testExecute_returnBlockNumber() throws Exception { - try (EvmcVm vm = EvmcVm.create(exampleVmPath)) { + try (EvmcVm vm = EvmcVm.create(libEvmcPath, exampleVmPath)) { HostContext context = new TestHostContext(); int BYZANTIUM = 4; int EVMC_CALL = 0; @@ -137,7 +138,7 @@ void testExecute_returnBlockNumber() throws Exception { /** Tests callbacks: get_tx_context_fn & set_storage_fn */ @Test void testExecute_saveReturnBlockNumber() throws Exception { - try (EvmcVm vm = EvmcVm.create(exampleVmPath)) { + try (EvmcVm vm = EvmcVm.create(libEvmcPath, exampleVmPath)) { HostContext context = new TestHostContext(); int BYZANTIUM = 4; int EVMC_CALL = 0; @@ -169,7 +170,7 @@ void testExecute_saveReturnBlockNumber() throws Exception { /** Tests callbacks: call_fn */ @Test void testExecute_makeCall() throws Exception { - try (EvmcVm vm = EvmcVm.create(exampleVmPath)) { + try (EvmcVm vm = EvmcVm.create(libEvmcPath, exampleVmPath)) { HostContext context = new TestHostContext(); int BYZANTIUM = 4; int EVMC_CALL = 0; @@ -207,7 +208,7 @@ void testExecute_makeCall() throws Exception { @Test void testExecute_EVMC_CREATE() throws Exception { - try (EvmcVm vm = EvmcVm.create(exampleVmPath)) { + try (EvmcVm vm = EvmcVm.create(libEvmcPath, exampleVmPath)) { HostContext context = new TestHostContext(); int BYZANTIUM = 4; int EVMC_CREATE = 3; @@ -235,7 +236,7 @@ void testExecute_EVMC_CREATE() throws Exception { @Test void testGetCapabilities() throws Exception { - try (EvmcVm vm = EvmcVm.create(exampleVmPath)) { + try (EvmcVm vm = EvmcVm.create(libEvmcPath, exampleVmPath)) { int capabilities = vm.get_capabilities(); assert (capabilities > 0); } @@ -243,7 +244,7 @@ void testGetCapabilities() throws Exception { @Test void testSetOption() throws Exception { - try (EvmcVm vm = EvmcVm.create(exampleVmPath)) { + try (EvmcVm vm = EvmcVm.create(libEvmcPath, exampleVmPath)) { int result = vm.set_option("verbose", "1"); assert (result == 0); } From 308354b0b6f63ae6e0ffbe9c00f58ded4df09be1 Mon Sep 17 00:00:00 2001 From: Antoine Toulme Date: Sat, 8 Aug 2020 17:40:58 -0700 Subject: [PATCH 2/2] make address(ByteBuffer) public --- bindings/java/java/src/main/java/org/ethereum/evmc/EvmcVm.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/java/java/src/main/java/org/ethereum/evmc/EvmcVm.java b/bindings/java/java/src/main/java/org/ethereum/evmc/EvmcVm.java index fc70d662b..957989b64 100644 --- a/bindings/java/java/src/main/java/org/ethereum/evmc/EvmcVm.java +++ b/bindings/java/java/src/main/java/org/ethereum/evmc/EvmcVm.java @@ -144,7 +144,7 @@ public int set_option(String name, String value) { * @param buffer the byte buffer to consider * @return the byte buffer address */ - native long address(ByteBuffer buffer); + public native long address(ByteBuffer buffer); /** This method cleans up resources */ @Override