Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial implementation of Java bindings #455

Merged
merged 1 commit into from
Dec 3, 2019

Conversation

jrhea
Copy link
Collaborator

@jrhea jrhea commented Nov 16, 2019

This PR implements bindings for Java. All tests pass on OSX and debian:lastest.

Punchlist

Code:

  • evmc_host_interface jni
  • evmc_host_interface java
  • evmc_vm interface jni
  • evmc_vm interface java

Tests:

  • Init
  • EVMC_CREATE
  • return_address
  • counter
  • return_block_number
  • save_return_block_number
  • make_a_call

Build

  • integrate into CI

Other

  • README.md to orient people who want to use java bindings

Resolves #137
helps with ethereum/ethereumj#1025

@jrhea jrhea force-pushed the java-bindings branch 10 times, most recently from 8cc47eb to 0c0b008 Compare November 19, 2019 05:11
@jrhea jrhea mentioned this pull request Nov 19, 2019
@jrhea jrhea marked this pull request as ready for review November 19, 2019 06:03
Copy link
Collaborator

@atoulme atoulme left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Got cosmetic feedback.

bindings/java/Dockerfile Outdated Show resolved Hide resolved
bindings/java/build.gradle Outdated Show resolved Hide resolved
bindings/java/c/evmc-vm.c Outdated Show resolved Hide resolved
Copy link
Collaborator

@mkalinin mkalinin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my standpoint there should be a pair of abstractions:

  • Evmc as a general interface to evmc
  • EvmcVM which is instantiated via Evmc.create(String filename) and effectively a VM instance

It looks organic to me and allows user to instantiate several VM instances at a time.

EvmcVM could implement AutoCloseable interface to utilize try-with-resources pattern.

bindings/java/c/evmc-vm.c Outdated Show resolved Hide resolved
bindings/java/c/host.c Outdated Show resolved Hide resolved
@chfast
Copy link
Member

chfast commented Nov 19, 2019

I enabled building of external PR. If you push more commits the CI jobs should run correctly.

@chfast
Copy link
Member

chfast commented Nov 19, 2019

You can also check #171.

@jrhea jrhea force-pushed the java-bindings branch 2 times, most recently from 513cc45 to ee6d68c Compare November 19, 2019 23:40
@jrhea
Copy link
Collaborator Author

jrhea commented Nov 20, 2019

From my standpoint there should be a pair of abstractions:

  • Evmc as a general interface to evmc
  • EvmcVM which is instantiated via Evmc.create(String filename) and effectively a VM instance

It looks organic to me and allows user to instantiate several VM instances at a time.

EvmcVM could implement AutoCloseable interface to utilize try-with-resources pattern.

That does sound nice, but realistically why I would want to call Evmc.create(filename) multiple times. It's a little awkward considering that I will only load the shared object once. @chfast pointed out in another comment that there is typically one long lived vm that can handle multiple concurrent calls. That being said, I have some work to do to make sure everything is thread safe.

@jrhea jrhea force-pushed the java-bindings branch 2 times, most recently from 8422c1d to 1d61ebb Compare November 20, 2019 02:07
@chfast
Copy link
Member

chfast commented Nov 20, 2019

From my standpoint there should be a pair of abstractions:

  • Evmc as a general interface to evmc
  • EvmcVM which is instantiated via Evmc.create(String filename) and effectively a VM instance

It looks organic to me and allows user to instantiate several VM instances at a time.
EvmcVM could implement AutoCloseable interface to utilize try-with-resources pattern.

That does sound nice, but realistically why I would want to call Evmc.create(filename) multiple times. It's a little awkward considering that I will only load the shared object once. @chfast pointed out in another comment that there is typically one long lived vm that can handle multiple concurrent calls. That being said, I have some work to do to make sure everything is thread safe.

We are using this abstraction in all language bindings. This is mostly to make sure the VM instance is automatically released and also it wraps execution result object to also make sure it is properly released. But still the EvmcVM stays a singleton in most cases.

I still have to review this PR. I also don't think introducing this abstraction in the first iteration is crucial. I'm also guessing your goal is to consume other VM, not to export Java one.

@mkalinin
Copy link
Collaborator

but realistically why I would want to call Evmc.create(filename) multiple times.

Fair point. My abstraction model came out of my understanding of evmc design but it looks overcomplicated from user's perspective. I'd then keep EvmcVM class with create or getInstance factory method which loads evmc lib if it's not yet loaded and creates an instance of VM with filename specified by user. This instance would keep track of own vm_handle and dispose it when it's not needed anymore (explicitly by a user or by try-with-resources pattern).

From my experience having a deal with statically stored state is not that convenient in some cases. What if you want to run two VM instances within the same JVM process? For example, to test whether two different implementations are conformant with each other; however, this is hardly the case for this bindings and not that good example.

To conclude, IMO it's better to get rid of statics, it would give more flexibility to the user. But I agree that this is not necessary at the moment and could be done on demand.

and also it wraps execution result object to also make sure it is properly released

Good point. evmc_result should be disposed when it's not needed likewise VM itself. Is there any other resources that requires explicit disposal?

Also, I think it worth to mention in the head of HostContext interface that its implementation should be thread-safe.

@jrhea
Copy link
Collaborator Author

jrhea commented Nov 20, 2019

@mkalinin, @chfast, @atoulme great discussion. Thanks to for the guidance. Tbh, I am still getting a feel for how this will be used so your input here is invaluable. I want to point out that the test coverage is abysmal at this point. That being said, it could potentially be merged assuming we document it as in progress (once @chfast reviews of course). An iterative approach might make it easier to review going fwd. 2k line PRs are incredibly difficult to review - sorry about that.

@jrhea
Copy link
Collaborator Author

jrhea commented Nov 20, 2019

We are using this abstraction in all language bindings. This is mostly to make sure the VM instance is automatically released and also it wraps execution result object to also make sure it is properly released. But still the EvmcVM stays a singleton in most cases.

Thanks for this and good point about ensuring the result object is properly released. I have some work to do on this front. I will keep it static (for now) and change it to the abstraction that you, @mkalinin and @atoulme all suggested.

I still have to review this PR. I also don't think introducing this abstraction in the first iteration is crucial.

I can stop now and wait for your review, or I can continue work. I think the size of the PR is starting to reach the point where it becomes difficult to review.

I'm also guessing your goal is to consume other VM, not to export Java one.

Yessir the goal is to consume another VM

@jrhea
Copy link
Collaborator Author

jrhea commented Nov 20, 2019

I'd then keep EvmcVM class with create or getInstance factory method which loads evmc lib if it's not yet loaded and creates an instance of VM with filename specified by user. This instance would keep track of own vm_handle and dispose it when it's not needed anymore (explicitly by a user or by try-with-resources pattern).

This was very well said and totally doable.

From my experience having a deal with statically stored state is not that convenient in some cases.

100% agree here

Good point. evmc_result should be disposed when it's not needed likewise VM itself. Is there any other resources that requires explicit disposal?

Good question.

Also, I think it worth to mention in the head of HostContext interface that its implementation should be thread-safe.

agreed. i am open to suggestions

Copy link
Member

@chfast chfast left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need gradle-wrapper.jar and gradlew?

Copy link
Member

@chfast chfast left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a quick review.

I've found some issues with the C code, most of them should be fixed before merging.

I'm also concern a bit about the build process. Can we actually live without adding gradle wrapper and assume gradle is installed? Is there also a concern about the gradle version?

bindings/java/Dockerfile Outdated Show resolved Hide resolved
bindings/java/c/evmc-vm.c Outdated Show resolved Hide resolved
bindings/java/c/host.h Outdated Show resolved Hide resolved
bindings/java/c/host.c Outdated Show resolved Hide resolved
bindings/java/c/evmc-vm.c Outdated Show resolved Hide resolved
bindings/java/c/evmc-vm.c Outdated Show resolved Hide resolved
circle.yml Show resolved Hide resolved
bindings/java/Makefile Show resolved Hide resolved

build:
mkdir -p $(OUT_DIR)
gcc $(DEBUG_FLAG) -c $(INCLUDES) -o $(OUT_DIR)/loader.o ../../lib/loader/loader.c
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this common to provide build scripts for C compilation? If yes, then I think JNI should be pulled to main cmake script and build with it. I can handle that later.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that'd be great if you could tie it into the main script. thanks!

@axic
Copy link
Member

axic commented Dec 2, 2019

Also as a measure before merging, can you enable C formatting checks?

In https://github.com/ethereum/evmc/blob/master/circle.yml#L67 change:

-          find examples include lib test -name '*.hpp' -o -name '*.cpp' -o -name '*.h' -o -name '*.c' | xargs clang-format -i
+          find bindings/java examples include lib test -name '*.hpp' -o -name '*.cpp' -o -name '*.h' -o -name '*.c' | xargs clang-format -i

Also useful to install clang-format and run (clang-format -i <filename>) locally on your source so it can fix it.

@axic
Copy link
Member

axic commented Dec 2, 2019

@jrhea and let me know when the PR is ready for a final review.

bindings/java/Makefile Outdated Show resolved Hide resolved
bindings/java/c/host.c Outdated Show resolved Hide resolved
bindings/java/c/host.h Outdated Show resolved Hide resolved
bindings/java/c/host.c Outdated Show resolved Hide resolved
@jrhea
Copy link
Collaborator Author

jrhea commented Dec 2, 2019

@jrhea and let me know when the PR is ready for a final review.

I believe it is ready for a final review

bindings/java/c/host.c Outdated Show resolved Hide resolved
@axic
Copy link
Member

axic commented Dec 2, 2019

From my side this looks okay for a merge (and adding other improvements later).

@jrhea do you want to squash these into a single commit (once @chfast gives his final review)?

@jrhea
Copy link
Collaborator Author

jrhea commented Dec 2, 2019

From my side this looks okay for a merge (and adding other improvements later).

@jrhea do you want to squash these into a single commit (once @chfast gives his final review)?

whatever your normal procedure is works for me.

@chfast
Copy link
Member

chfast commented Dec 2, 2019

From my side this looks okay for a merge (and adding other improvements later).
@jrhea do you want to squash these into a single commit (once @chfast gives his final review)?

whatever your normal procedure is works for me.

This is not normal procedure, but because it only adds new stuff and has a reformat commit in the middle, I prefer to squash it.

Also, please add a changelog entry.

I actually have some number of suggestions for improvements, but it will be better to merge it as it is and follow up with future PRs.

@jrhea
Copy link
Collaborator Author

jrhea commented Dec 2, 2019

This is not normal procedure, but because it only adds new stuff and has a reformat commit in the middle, I prefer to squash it.

ok that's fine, then squash it. I only added the reformat commit bc i was asked to.

Also, please add a changelog entry.

done.

I actually have some number of suggestions for improvements, but it will be better to merge it as it is and follow up with future PRs.

ditto...it was a good first pass at least.

@axic axic changed the base branch from java to master December 3, 2019 12:20
Includes JNI bindings, tests and build system
@axic axic changed the title Initial Java bindings Initial implementation of Java bindings Dec 3, 2019
@axic
Copy link
Member

axic commented Dec 3, 2019

Thanks @jrhea for the work and @mkalinin @atoulme for the reviews!

@chfast chfast merged commit 33cd500 into ethereum:master Dec 3, 2019
@jrhea jrhea deleted the java-bindings branch December 3, 2019 13:27
@jrhea
Copy link
Collaborator Author

jrhea commented Dec 3, 2019

Thanks @jrhea for the work and @mkalinin @atoulme for the reviews!

sure thing. it was fun. thanks all for the reviews

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Create Java (JNI) binding
5 participants