Java vs C++ speed (IO & Sorting)

T

Thomas J. Gritzan

zionz said:
Could you verify this one:

void getRandomString(std::string &s)
{
int n,i;
srand((unsigned)std::time(0));
s.reserve(len);
for(i = 0 ; i < len; i+=4){
n = rand();
s+= (char) (n % 26 + 97);
s+= (char) ( (n>>8) % 26 + 97);
s+= (char) ( (n>>16) % 26 + 97);
s+= (char) ( (n>>24) % 26 + 97);
}
}

btw it seems the c++ rand() is slower than the java equivalent, and in
this test theres no real way of optimizing the things since everything
depends on that function.

Try this one:

// version by tjg
void randomString(std::string &s)
{
srand((unsigned)std::time(0));
s.resize(len);
for( int i = 0 ; i+3 < len; i+=4 ){
int n = rand();
s[i+0] = (char) (n % 26 + 97); n /= 26;
s[i+1] = (char) (n % 26 + 97); n /= 26;
s[i+2] = (char) (n % 26 + 97); n /= 26;
s[i+3] = (char) (n % 26 + 97);
}
}
 
Z

zionz

zionz said:
Could you verify this one:
void getRandomString(std::string &s)
{
int n,i;
srand((unsigned)std::time(0));
s.reserve(len);
for(i = 0 ; i < len; i+=4){
n = rand();
s+= (char) (n % 26 + 97);
s+= (char) ( (n>>8) % 26 + 97);
s+= (char) ( (n>>16) % 26 + 97);
s+= (char) ( (n>>24) % 26 + 97);
}
}
btw it seems the c++ rand() is slower than the java equivalent, and in
this test theres no real way of optimizing the things since everything
depends on that function.

Try this one:

// version by tjg
void randomString(std::string &s)
{
srand((unsigned)std::time(0));
s.resize(len);
for( int i = 0 ; i+3 < len; i+=4 ){
int n = rand();
s[i+0] = (char) (n % 26 + 97); n /= 26;
s[i+1] = (char) (n % 26 + 97); n /= 26;
s[i+2] = (char) (n % 26 + 97); n /= 26;
s[i+3] = (char) (n % 26 + 97);
}

}

Using that code i get:

runtime: 830 ms
'a' count: 110
'z' count: 109
"zion" count: 1923151
"adam" count: 1921978

This is the best one so far :D.
 
Z

zionz

Using that code i get:
runtime: 830 ms
'a' count: 110
'z' count: 109
"zion" count: 1923151
"adam" count: 1921978

This is the best one so far :D.

sorry i mixed the letters with the names there.
 
Y

Yannick Tremblay

My guts feeling is that using multiset would be much slower than
sorting a vector.

There was Stepanov/Stroustrup bechmark a couple of years ago comparing
use of various containers/methods at "remove duplicit strings"
problem.

Loading all strings into vector, sorting and using std::unique has won
hands down.

Mirek

http://www.stepanovpapers.com/container_benchmark.cpp

Your recollection is correct. However, this might not apply to the
(bad) speed test program posted by the OP.

In Stepanov test, the containers contain doubles. In the OP program,
the containers contain relatively large strings (complete line of text
maybe 10 to 200 bytes?). The suggested C++ code stores these lines as
values (while the Java code stores them as pointers), and sorting
requires comparing and copying/moving of the stored data. So while
the performance advantage of vectors over sets might overcome the
copying of doubles, it might not overcome the copying of large
strings.

With a few modifications to the program above, using a vector of
string of random integers with duplicated elements, I get the
following:

doubles:
size vector iter set multiset
10 1.15 1.60 2.65
100 0.60 1.47 2.24
1000 0.91 1.55 1.97
10000 0.83 1.84 2.65

basic_string<int> 1 integers
size vector iter set multiset
10 3.88 0.92 4.37
100 2.02 0.38 2.29
1000 1.57 0.27 1.60
10000 1.64 0.23 1.35

basic_string<int> 10 integers
size vector iter set multiset
10 7.93 3.86 5.84
100 5.11 2.88 4.12
1000 4.01 2.62 3.60
10000 4.08 4.27 6.09

basic_string<int> 100 integers
size vector iter set multiset
10 9.66 5.49 8.02
100 5.93 3.56 5.20
1000 4.82 3.32 4.66
10000 5.83 5.46 7.89

basic_string<int> 1000 integers
size vector iter set multiset
10 35.50 26.50 34.76
100 19.18 13.56 18.61
1000 15.53 11.36 15.89
10000 13.67 12.13 16.56


The expensive copying/moving of string can be eliminated by
using basic_string<int> * as as content of the containers (and
supplying approriate predicate functions for sorting on the content of
the pointer. Totally neglecting memory management, simply new-ing
basic_string and storing the pointer in a vector (note that this is a
lot closer to what the Java program in the OP test code does since in
Java, essentially everything are pointers and he was ignoring
garbage collection time, so that gives us a much more comparable test
with Java)

For example, with 100 ints in the strings:
size vector<basic_string<int> > vector<basic_string<int> *>
10 7.93 5.07
100 5.11 3.57
1000 4.01 3.35
10000 4.08 4.78

with 1000 ints in the strings:
size vector<basic_string<int> > vector<basic_string<int> *>
10 35.50 29.89
100 19.18 16.62
1000 15.53 14.19
10000 13.67 12.42


All that goes to show how non-obvious performance can be.

Yannick
 
M

Mirek Fidler

http://www.stepanovpapers.com/container_benchmark.cpp

Your recollection is correct. However, this might not apply to the
(bad) speed test program posted by the OP.

Yes. Meanwhile I have tried the benchmark myself and multiset really
is a bit faster.
values (while the Java code stores them as pointers), and sorting
requires comparing and copying/moving of the stored data.

Well, I am not an std::/STL expert, but I always thought that sort
does not actually need to copy/move pointed character data, just
exchange pointers by overloaded swap... (at least, this is what we do
in U++). It is however true that sorting part of this benchmark is
twice as fast if this whole thing is implemented in U++, so you might
be right..
All that goes to show how non-obvious performance can be.

Hehe, indeed. OTOH, there is so much fun with it :)

Mirek
 
R

Razii

That doesn't make sense. Options to the 'java' command aren't in any
directory. It's the 'java' executable itself that resides in the file system.
Options are provided upon its invocation. There is no separate "version" of
the executable.

Are you sure?

Here is my PATH variable

C:\Program
Files\Java\SDK\jdk\bin;C:\jet6.0-eval\bin;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem

if I change the above to this...

;C:\jet6.0-eval\bin;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;C:\Program
Files\Java\SDK\jdk\bin

I get

C:\>java -server Test

Error: no `server' JVM at `C:\Program
Files\Java\jre1.6.0_05\bin\server\jvm.dll'

After I move the JDK directory back to

C:\Program
Files\Java\SDK\jdk\bin;C:\jet6.0-eval\bin;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem

C:\>java -Xmx256m -server Find a
Number of a: 1923593
Time: 1723 ms
 
R

Razii

Try this one:

// version by tjg
void randomString(std::string &s)
{
srand((unsigned)std::time(0));
s.resize(len);
for( int i = 0 ; i+3 < len; i+=4 ){
int n = rand();
s[i+0] = (char) (n % 26 + 97); n /= 26;
s[i+1] = (char) (n % 26 + 97); n /= 26;
s[i+2] = (char) (n % 26 + 97); n /= 26;
s[i+3] = (char) (n % 26 + 97);
}
}


Doesn't work.... Using the above, I get...

C:\>Find2
Time: 0.751
Results:
0
808
8185895
1215421

No zion but 808 adam? Trying again...

C:\>Find2
Time: 0.704
Results:
0
766
8188734
1215008

Same problems....

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>

using namespace std;

const int len = 50000000;

void getRandomString(std::string &s)
{
srand((unsigned)std::time(0));
s.resize(len);
12:25 PM 3/26/2008 for( int i = 0 ; i+3 < len; i+=4 ){
int n = rand();
s[i+0] = (char) (n % 26 + 97); n /= 26;
s[i+1] = (char) (n % 26 + 97); n /= 26;
s[i+2] = (char) (n % 26 + 97); n /= 26;
s[i+3] = (char) (n % 26 + 97);
}
}

int main()
{
int i,ac,zc,a,b;
ac=zc=a=b=0;

clock_t start=clock();
string s;
getRandomString(s);
clock_t endt=clock();
cout << "Time: " << (double)(endt-start) /
(double)CLOCKS_PER_SEC <<

endl;

for(i=0; i<s.size(); i++){
if(s == 'a'){ a++;}
if(s == 'z'){ b++;}
if(s.substr(i,4) == "adam"){zc++;}
if(s.substr(i,4) == "zion"){ac++;}
}

cout << "Results: " << endl << ac << endl << zc << endl;
cout << a << endl << b << endl;
}
 
Y

Yannick Tremblay

Well, I am not an std::/STL expert, but I always thought that sort
does not actually need to copy/move pointed character data, just
exchange pointers by overloaded swap... (at least, this is what we do
in U++). It is however true that sorting part of this benchmark is
twice as fast if this whole thing is implemented in U++, so you might
be right..

Unfortunately I guess the answer is: it depends.

a std::vector is a contiguous container so sorting it will require
swapping value objects or copy construction. For POD-types it
definitely mean copying the data since that's the only way you will
still be able to iterate contiguously over the data. For more complex
objects: it depends :-( sort will still have to copy something, but
the object might be optimised for swapping their internal private
data.

On the other hand, a std::list is typically implemented as a linked
list so it should possible to sort it only by moving the next/previous
pointers never actually touching the data. But this is implementation
dependent.

Which is faster also varies. For example, if you have a
std::list<int> implemented as a double linked list, then swapping the
content (modifying 2 int) should be faster than modifying the 4
pointers.

Note that when using long string, comparing also becomes expensive,
another reason why the original double version is much faster than my
modified basic_string<int> version which probably explains why
although faster, storing pointers to strings still suffer performance
degradation as string lenght increases.

Yan
 
Z

zionz

Try this one:
// version by tjg
void randomString(std::string &s)
{
srand((unsigned)std::time(0));
s.resize(len);
for( int i = 0 ; i+3 < len; i+=4 ){
int n = rand();
s[i+0] = (char) (n % 26 + 97); n /= 26;
s[i+1] = (char) (n % 26 + 97); n /= 26;
s[i+2] = (char) (n % 26 + 97); n /= 26;
s[i+3] = (char) (n % 26 + 97);
}
}

Doesn't work.... Using the above, I get...

C:\>Find2
Time: 0.751
Results:
0
808
8185895
1215421

No zion but 808 adam? Trying again...

C:\>Find2
Time: 0.704
Results:
0
766
8188734
1215008

Same problems....

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>

using namespace std;

const int len = 50000000;

void getRandomString(std::string &s)
{
srand((unsigned)std::time(0));
s.resize(len);
12:25 PM 3/26/2008 for( int i = 0 ; i+3 < len; i+=4 ){
int n = rand();
s[i+0] = (char) (n % 26 + 97); n /= 26;
s[i+1] = (char) (n % 26 + 97); n /= 26;
s[i+2] = (char) (n % 26 + 97); n /= 26;
s[i+3] = (char) (n % 26 + 97);
}

}

int main()
{
int i,ac,zc,a,b;
ac=zc=a=b=0;

clock_t start=clock();
string s;
getRandomString(s);
clock_t endt=clock();
cout << "Time: " << (double)(endt-start) /
(double)CLOCKS_PER_SEC <<

endl;

for(i=0; i<s.size(); i++){
if(s == 'a'){ a++;}
if(s == 'z'){ b++;}
if(s.substr(i,4) == "adam"){zc++;}
if(s.substr(i,4) == "zion"){ac++;}
}

cout << "Results: " << endl << ac << endl << zc << endl;
cout << a << endl << b << endl;

}


I tried with MS VC++ 2008 express edition, the difference is in the
value of RAND_MAX:

g++ RAND_MAX = 2147483647
vc++ RAND_MAX = 32767

However the problem can be solved by using an extra rand() call:

void getRandomString(std::string &s)
{
srand((unsigned)std::time(0));
s.resize(len);
for( int i = 0 ; i+3 < len; i+=4 ){
int n = rand();
s[i+0] = (char) (n % 26 + 97); n /= 26;
s[i+1] = (char) (n % 26 + 97);
n = rand();
s[i+2] = (char) (n % 26 + 97); n /= 26;
s[i+3] = (char) (n % 26 + 97);
}
}
 
T

Thomas J. Gritzan

zionz said:
I tried with MS VC++ 2008 express edition, the difference is in the
value of RAND_MAX:

g++ RAND_MAX = 2147483647
vc++ RAND_MAX = 32767

However the problem can be solved by using an extra rand() call:

void getRandomString(std::string &s)
{
srand((unsigned)std::time(0));
s.resize(len);
for( int i = 0 ; i+3 < len; i+=4 ){
int n = rand();
s[i+0] = (char) (n % 26 + 97); n /= 26;
s[i+1] = (char) (n % 26 + 97);
n = rand();
s[i+2] = (char) (n % 26 + 97); n /= 26;
s[i+3] = (char) (n % 26 + 97);
}
}

That doubles time on my test machine.

We should take a common library instead, so that the different library
implementations don't make a difference.

I tried this code, more than doubled the speed on my machine (from the
one-rand() version):

// include at top:
#include <boost/random.hpp>

// boost version by tjg
void randomString(std::string &s)
{
boost::rand48 rnd(static_cast<uint64_t>(std::time(0)));
s.resize(len);
for( int i = 0 ; i+3 < len; i+=4 ){
int n = rnd();
s[i+0]= (char) (n % 26 + 97); n /= 26;
s[i+1]= (char) (n % 26 + 97); n /= 26;
s[i+2]= (char) (n % 26 + 97); n /= 26;
s[i+3]= (char) (n % 26 + 97);
}
}
 
Z

zionz

zionz said:
I tried with MS VC++ 2008 express edition, the difference is in the
value of RAND_MAX:
g++ RAND_MAX = 2147483647
vc++ RAND_MAX = 32767
However the problem can be solved by using an extra rand() call:
void getRandomString(std::string &s)
{
srand((unsigned)std::time(0));
s.resize(len);
for( int i = 0 ; i+3 < len; i+=4 ){
int n = rand();
s[i+0] = (char) (n % 26 + 97); n /= 26;
s[i+1] = (char) (n % 26 + 97);
n = rand();
s[i+2] = (char) (n % 26 + 97); n /= 26;
s[i+3] = (char) (n % 26 + 97);
}
}

That doubles time on my test machine.

We should take a common library instead, so that the different library
implementations don't make a difference.

I tried this code, more than doubled the speed on my machine (from the
one-rand() version):

// include at top:
#include <boost/random.hpp>

// boost version by tjg
void randomString(std::string &s)
{
boost::rand48 rnd(static_cast<uint64_t>(std::time(0)));
s.resize(len);
for( int i = 0 ; i+3 < len; i+=4 ){
int n = rnd();
s[i+0]= (char) (n % 26 + 97); n /= 26;
s[i+1]= (char) (n % 26 + 97); n /= 26;
s[i+2]= (char) (n % 26 + 97); n /= 26;
s[i+3]= (char) (n % 26 + 97);
}

}

True but here even using 2 rand() calls it resulted faster than the
java version (940ms vs 1650ms)

btw, using your boost code i get much better results (not tested on
windows):

time: 370 ms
Results:
111 ('a')
110 ('z')
1922428 ("zion")
1921497 ("adam")
 
J

James Kanze

Try this one:
// version by tjg
void randomString(std::string &s)
{
srand((unsigned)std::time(0));
s.resize(len);
for( int i = 0 ; i+3 < len; i+=4 ){
int n = rand();
s[i+0] = (char) (n % 26 + 97); n /= 26;
s[i+1] = (char) (n % 26 + 97); n /= 26;
s[i+2] = (char) (n % 26 + 97); n /= 26;
s[i+3] = (char) (n % 26 + 97);
}
}

For various historical reasons, RAND_MAX is only about 32768 on
a lot of machines. Which means that the last character in the
block of four isn't going to be very random.
 
R

Razii

// boost version by tjg
void randomString(std::string &s)
{
boost::rand48 rnd(static_cast<uint64_t>(std::time(0)));
s.resize(len);
for( int i = 0 ; i+3 < len; i+=4 ){
int n = rnd();
s[i+0]= (char) (n % 26 + 97); n /= 26;
s[i+1]= (char) (n % 26 + 97); n /= 26;
s[i+2]= (char) (n % 26 + 97); n /= 26;
s[i+3]= (char) (n % 26 + 97);
}

}

True but here even using 2 rand() calls it resulted faster than the
java version (940ms vs 1650ms)

How are you comparing that with Java? I can change the function in
Java too :)

After changes,, the new times I am getting on java are..

C:\>java -Xmx256m -server Find a
Number of a: 1929940
Time: 956 ms

C:\>java -Xmx256m -server Find z
Number of z: 1833020
Time: 925 ms

C:\>java -Xmx256m -server Find p
Number of p: 1930647
Time: 908 ms

The randomness is pretty good except for z and y which are slightly
lower ..

That time is 2 times faster than the last java version...

static String randomString(int len)
{
int i, n;
char[] cr = new char[len];
Random rd = new Random();
for(i = 0 ; i < len; i+=4)
{ n = rd.nextInt(2147483647);
cr = (char) (n % 26 + 97);
cr[i+1] = (char) ( (n>>8) % 26 + 97);
cr[i+2] = (char) ( (n>>16) % 26 + 97);
cr[i+3] = (char) ( (n>>24) % 26 + 97);
}
return new String(cr);
}
 
R

Razii

We should take a common library instead, so that the different library
implementations don't make a difference.

If your version doesn't work on my computer with my compiler, what
good is it? The version must work with most standard compilers.
 
Z

zionz

// boost version by tjg
void randomString(std::string &s)
{
boost::rand48 rnd(static_cast<uint64_t>(std::time(0)));
s.resize(len);
for( int i = 0 ; i+3 < len; i+=4 ){
int n = rnd();
s[i+0]= (char) (n % 26 + 97); n /= 26;
s[i+1]= (char) (n % 26 + 97); n /= 26;
s[i+2]= (char) (n % 26 + 97); n /= 26;
s[i+3]= (char) (n % 26 + 97);
}
}
True but here even using 2 rand() calls it resulted faster than the
java version (940ms vs 1650ms)

How are you comparing that with Java? I can change the function in
Java too :)

After changes,, the new times I am getting on java are..

C:\>java -Xmx256m -server Find a
Number of a: 1929940
Time: 956 ms

C:\>java -Xmx256m -server Find z
Number of z: 1833020
Time: 925 ms

C:\>java -Xmx256m -server Find p
Number of p: 1930647
Time: 908 ms

The randomness is pretty good except for z and y which are slightly
lower ..

That time is 2 times faster than the last java version...

static String randomString(int len)
{
int i, n;
char[] cr = new char[len];
Random rd = new Random();
for(i = 0 ; i < len; i+=4)
{ n = rd.nextInt(2147483647);
cr = (char) (n % 26 + 97);
cr[i+1] = (char) ( (n>>8) % 26 + 97);
cr[i+2] = (char) ( (n>>16) % 26 + 97);
cr[i+3] = (char) ( (n>>24) % 26 + 97);
}
return new String(cr);
}


Using that new func the java version now takes 983ms avg, the c++
version using 2 rand() calls is taking 947ms avg, so they are pretty
even, using the boost lib makes a big difference since it only takes
360ms avg.

Btw the java code works on char array that is copied into a string
(class?) i guess thats why it needs about 2x ram, what about
implementing it more like the c++ version?
 
R

Razii

static String randomString(int len)
{
int i, n;
char[] cr = new char[len];
Random rd = new Random();
for(i = 0 ; i < len; i+=4)
{ n = rd.nextInt(2147483647);
cr = (char) (n % 26 + 97);
cr[i+1] = (char) ( (n>>8) % 26 + 97);
cr[i+2] = (char) ( (n>>16) % 26 + 97);
cr[i+3] = (char) ( (n>>24) % 26 + 97);
}
return new String(cr);
}



Ignore that version... try the follwing (same time but z and y numbers
were fine).

static String randomString(int len)
{
int n;
char[] cr = new char[len];
Random rd = new Random();
for( int i = 0 ; i+3 < len; i+=4 ){
n = rd.nextInt(2147483647);
cr[i+0] = (char) (n % 26 + 97); n /= 26;
cr[i+1] = (char) (n % 26 + 97); n /= 26;
cr[i+2] = (char) (n % 26 + 97); n /= 26;
cr[i+3] = (char) (n % 26 + 97);
}
return new String(cr);
}

}
 
R

Razii

Btw the java code works on char array that is copied into a string
(class?) i guess thats why it needs about 2x ram, what about
implementing it more like the c++ version

You mean String s;

forloop { s += 'char'; }

It will be way slower because String in java are immutable and with
each loop, a new string object will be created.

The quote below is from http://www.acooke.org/andrew/immutable.html

the contents of the String class cannot be changed. any method that
you might expect to modify the contents actually returns a new
instance.

if you don't like this behaviour you might think of sub-classing
String to provide methods that do alter the contents. but this isn't
possible because the class is "final".

to see why, i think you have to look at how java passes arguments.
machine-level values - ints, floats and the like - are passed by
value. if you call foo.bar(i) then modifying the passed integer within
the bar method won't alter the value of i (of course!).

however, if we pass an object into a method, where the object's
contents are changed, then the effect will be seen outside the call.
this is passing by reference:

class Foo {
void changeStack( Stack inside ) {
inside.pop( ) ;
}
}

Stack s ;
s.push( new Object( ) ) ;
System.out.println( s.size( ) ) ; // here s has size 1
Foo f = new Foo( ) ;
f.changeStack( s ) ;
System.out.println( s.size( ) ) ; // here s has size 0

again, this is obvious, but note that it is different to the way in
which the machine-level values behave.

so how does this apply to String? unlike ints, literal strings
(sequences of characters in quotes) are not machine-level values -
they are String objects. so, in theory, passing "a quoted string" to a
method might result in the string changing value!

class FooFoo {
void changeString( String inside ) {
inside.append( " world" ) ; // pretend this changes the
String...
}
}

String s = "hello" ;
Foo f = new Foo( ) ;
f.changeString( s ) ;
System.out.println( s ) ; // ...then this would be "hello
world"...

f.changeString( "strange" ) ; // ...and what happens here?!

to avoid strange things like this last value (where a quoted string
would change value) the java designers would either have to have make
"quoted strings" machine-level values or introduce the idea of const
objects (similar to C++).

instead, the pragmatic solution is to make sure that the Sting class
can't change its contents - hence it is immutable and final.

and because String is immutable and final, it behaves as though it is
passed by value, not reference.
 
L

Lew

Razii said:
Are you sure?
Yes.

Here is my PATH variable

C:\Program
Files\Java\SDK\jdk\bin;C:\jet6.0-eval\bin;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem

if I change the above to this...

;C:\jet6.0-eval\bin;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;C:\Program
Files\Java\SDK\jdk\bin

I get

C:\>java -server Test

Note that the call here is to the 'java' executable.
Error: no `server' JVM at `C:\Program
Files\Java\jre1.6.0_05\bin\server\jvm.dll'

After I move the JDK directory back to

C:\Program
Files\Java\SDK\jdk\bin;C:\jet6.0-eval\bin;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem

C:\>java -Xmx256m -server Find a
Number of a: 1923593
Time: 1723 ms

This doesn't prove anything. Only that there is a problem in the
'jre1.6.0_05' installation. You will note that the path mentioned in the error,
C:\Program Files\Java\jre1.6.0_05\bin\server\
is not in your PATH.
 
R

Razii

Only that there is a problem in the
'jre1.6.0_05' installation.

There is nothing wrong with my installation. Server VM doesn't ship
with JRE. It only comes with full JDK download.

The following is from the readme file in the Sun JDK:

On Microsoft Windows platforms, the JDK includes both
the Java HotSpot(TM) Server VM and Java HotSpot Client VM.
However, the Java SE Runtime Environment for Microsoft Windows
platforms includes only the Java HotSpot Client VM. Those wishing
to use the Java HotSpot Server VM with the Java SE Runtime
Environment may copy the JDK's jre\bin\server folder to a
bin\server directory in the Java SE Runtime Environment. Software
vendors may redistribute the Java HotSpot Server VM with their
redistributions of the Java SE Runtime Environment.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,176
Messages
2,570,947
Members
47,498
Latest member
log5Sshell/alfa5

Latest Threads

Top