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
java.net.Socket implementation #97
Conversation
@bigfatbrowncat , could you take a look at the travis build failures? |
private final int port; | ||
|
||
public InetSocketAddress(String host, int port) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Nice work, overall! |
Thank you for your attention. I'll fix that. Strange, but it has builded on my site… |
I've fixed all the problems, now it builds well. |
@bigfatbrowncat you probably built with |
@bigfatbrowncat, could you squash the existing commits, and then add a test along the lines of SendFile and/or SendServer? |
Okay, I'll try to squash the commits. I'm working on ServerSocket now. After that I'll make a test code - send a file from client Socket to a ServerSocket on localhost. Would it be a proper test? |
Now it works on OS X Small improvements Added bufferes I/O Small fixes Added getHostName() function
I'm sorry for creating a mess, that was the first time I squashed commits. I will recreate a new pull request with the new branch. |
} | ||
|
||
extern "C" JNIEXPORT char* JNICALL | ||
Java_java_net_Socket_allocateBuffer(JNIEnv*, jclass, int buf_size) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question is whether that's not better handled with https://github.com/ReadyTalk/avian/blob/master/classpath/sun/misc/Unsafe.java#L14 and https://github.com/ReadyTalk/avian/blob/master/classpath/sun/misc/Unsafe.java#L19?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made specific methods for using with socket streams. The advantage of implementing everything necessary right here is good encapsulation. We don't call an outer class for a trivial operation. Do you really think we should depend on Unsafe here?
Which disadvantages do you see here (except of duplication of a trivial function)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @dscho for a number of reasons:
- I'd rather avoid allocating memory not managed by the VM in a non-local fashion
- The approach pointed out below (reading directly into the byte buffer) should be more performant (and not require any native allocations)
- Java methods can easily be stripped out at build time by proguard, but there's no such tool for jni methods - so I'd like to minimize the latter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Ok, I will use Unsafe if you insist (you are the boss, after all ;) ).
- About reading directly to a buffer - this is not JNI-style, it's Avian-specific. I just haven't known about it yet. Could you tell me more about using it? I could dig by myself, of course, but it would be great if you explain which functions/methods to use and I'll use them.
- I understand your position well. I'll try to minimize the native code as tight as I could.
By the way (just an idea), there is method which could help you to shrink native binary. You could divide the default library into some parts (java classes + JNI code) and turn them on and off during compilation. For example if I don't want networking I would exclude the whole java.net package with java-net.cpp.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course, the best solution is if you can avoid Unsafe completely ( - but there are lots of competing ideals, and we're unlikely to optimize them all.
(you are the boss, after all)
Technically, I'm just filling in for a while... :)
Could you tell me more about using it?
Sure. Avian supports two types of external functions: Java_ methods (jni) and Avian_ methods (avian-specific, referred to as the "fast" path in the code). Java_ methods should be compatible with every other jvm implementation (if they're not, it's a bug). They take arguments as normal C arguments. Avian_ methods take arguments in a single uintptr_t* array - which allows us to bypass a lot of platform-specific native code. The first argument will be at index 0 in that array, and so on.
The key with Avian_ methods in this context is that there's the unwritten assumption that, since they're already using avian-specific code, they might as well dig further into the internals. That gives us license to use byteArrayBody, an avian-specific utility method for retrieving a reference to an element in a Java-level byte array. Thus, we can ask for the zeroth element and take the address to yield a pointer directly to the buffer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you propose to implement send and recv as Avian_ native methods and read/write directly to the buffer?
Ok, I'll try to do that.
Here is the new version.
Do you have any other comments? |
So... I mentioned a " test along the lines of SendFile and/or SendServer" without actually having read over that code. Oops. In particular, they live in the test/extra directory and don't actually get executed with the other tests. They must be manually executed. On the other hand, they also don't make any requests out of the local machine (well, unless you tell them to on the command line) - which I think is important for unit tests (even though they're not really unit tests). If possible, I think the best test would be one that spins up an extra thread and sends a short string between that thread and the main one via your new socket implementation. Also, see my comment(s) on the travis build failures. |
I have a problem. I tried to build this code under OS X (yes, you were right, I had to write reinterpret_cast), but it wouldn't compile. The short story: I can't use "jni.h" and "avian/machine.h" included in the same file. They are conflicting. But I need both. If I don't include the second, I can't use I have some hacking ideas about how to make them friends, but I want to know the "official" way. Could you propose me how should I do? |
@bigfatbrowncat are you sure you need to call |
@bigfatbrowncat , I agree with @dscho that |
I agree too (about I merged all the latest commits into my fork and fixed bugs. Could you look at the most recent version, please? |
Hmm… strange build error. I don't have such a bug under OS X. I'll check it under Win7... |
I found this bug in Win7 and fixed it. It's just a piece of C linker magic. |
Hmm... now it builds under Win7, but still doesn't build in Travis. I don't have a linux machine here. Could you check? |
@bigfatbrowncat I removed another incompatibility between jni.h and avian's common.h in 2800ffe. That seems to fix the linux build. Could you pull and verify on your end? |
It builds on OS X and under Win7 x64. And all the tests work like a charm. Finally! |
I've squashed the commits in this PR and merged them: 45ee25f Thanks, @bigfatbrowncat ! |
I created a basic clean-room implementation of java.net.Socket class (and improved some connected additional classes).
The implementation doesn't contain all the methods of the original one, but it is sufficient to connect to a remote server and send/receive data.
I tested it by connecting to an HTTP-server under Windows 7 and OS X 10.8. It works satisfactory.
As for now only TCP-socket is implemented for IPv4 addresses.
If you accept this pull-request I'll try to resolve all possible bugs connected to it. And in addition I'm going to implement ServerSocket soon.