Re: Compiler program platform-independant?

Discussion in 'Java' started by Lew, Jan 6, 2011.

  1. Lew

    Lew Guest

    On Jan 6, 1:13 pm, Julien ÉLIE <>
    wrote:
    > Hi,
    >
    > If I use the same version of the same compiler (for instance “javac”
    > provided by Sun) on different OS and hardwares (for instance a 32-bit
    > Linux Debian, a 32-bit FreeBSD, and a 64-bit Windows 7), will the
    > generated Java bytecode be exactly the same?
    > And if it is the same OS on two different computers?
    >
    > Of course, the Java source code is the same, and so are the compiler
    > options.
    >
    > I ask because I wonder whether two different .class files imply that the
    > .java files from which they were compiled (with the same compiler), are
    > different.


    The bytecode depends only on the Java version that compiled it and not
    at all on the JRE that runs it or the vendor who produced it or the
    source or target platform.

    As for there being "some differences in the compiled JRE" or whether
    "implementation of libraries" being the same, that has no bearing on
    your question.

    Remember, Java's slogan is, "Write once, run everywhere". Bytecode
    is platform independent by definition.

    --
    Lew
    Lew, Jan 6, 2011
    #1
    1. Advertising

  2. Lew

    BGB Guest

    On 1/6/2011 2:58 PM, TheGunslinger wrote:
    > On Thu, 6 Jan 2011 12:19:53 -0800 (PST), Lew<>
    > wrote:
    >
    >> On Jan 6, 1:13 pm, Julien ÉLIE<>
    >> wrote:
    >>> Hi,
    >>>
    >>> If I use the same version of the same compiler (for instance “javac”
    >>> provided by Sun) on different OS and hardwares (for instance a 32-bit
    >>> Linux Debian, a 32-bit FreeBSD, and a 64-bit Windows 7), will the
    >>> generated Java bytecode be exactly the same?
    >>> And if it is the same OS on two different computers?
    >>>
    >>> Of course, the Java source code is the same, and so are the compiler
    >>> options.
    >>>
    >>> I ask because I wonder whether two different .class files imply that the
    >>> .java files from which they were compiled (with the same compiler), are
    >>> different.

    >>
    >> The bytecode depends only on the Java version that compiled it and not
    >> at all on the JRE that runs it or the vendor who produced it or the
    >> source or target platform.
    >>
    >> As for there being "some differences in the compiled JRE" or whether
    >> "implementation of libraries" being the same, that has no bearing on
    >> your question.
    >>
    >> Remember, Java's slogan is, "Write once, run everywhere". Bytecode
    >> is platform independent by definition.

    >
    > Actually, it is exactly what was being asked.
    >
    > The generic.java code is compiled into generic.class code which is
    > what gets interpreted by the jre.
    >
    > On different platforms, there is no guarantee that the generic.class
    > (bytecode) code is going to be exactly the same, only that it performs
    > the same and gives the same results.
    >


    yeah, just as different versions of 'javac' and different
    implementations of a java compiler, are liable to give bytecode with
    minor differences even though both the source code and run-time behavior
    are likely to remain equivalent.


    a simple example could be that the compilers differ in terms of things
    like which order entries end up in the constant pool.

    for example, the Sun/Oracle javac seems to basically put all the
    depended-on entries into the constant pool prior to those that depend on
    them, whereas IBM's javac seems to do the reverse, with prior
    constant-pool entries typically depending on latter ones (I could be
    wrong here, this is just something I noted in the past).

    another difference would likely be in terms of exact bytecode sequences
    produced (where multiple possible sequences can produce the same results
    in some cases), ...

    but, the same version of the same compiler should (presumably) produce
    the same output regardless of OS or CPU architecture in use (although
    there is always a certain level of possibility of pseudo-random effects
    or similar, so one can't always be certain).


    however, most of this will have litte/no impact on what happens when the
    code is run.


    or such...
    BGB, Jan 6, 2011
    #2
    1. Advertising

  3. Lew

    markspace Guest

    On 1/6/2011 3:05 PM, Julien ÉLIE wrote:

    > Suppose I have test.java and I want to compile it with Java SE 6 Update
    > 23 on different OSes and hardwares; would it generate the same
    > test.class file ("the same" means that it is exactly the same file --
    > same MD5 checksum for instance).



    I think everyone has consistently been saying 1) we don't know, and 2)
    Sun/Oracle doesn't seem to make any such guarantee.

    I think you are likely to get exactly the same byte codes, but I
    wouldn't count on it. If your process will absolutely break due to
    different byte codes, make a more robust process.
    markspace, Jan 6, 2011
    #3
  4. On Thu, 06 Jan 2011 15:24:34 -0800, markspace wrote:

    > On 1/6/2011 3:05 PM, Julien ÉLIE wrote:
    >
    >> Suppose I have test.java and I want to compile it with Java SE 6 Update
    >> 23 on different OSes and hardwares; would it generate the same
    >> test.class file ("the same" means that it is exactly the same file --
    >> same MD5 checksum for instance).

    >
    >
    > I think everyone has consistently been saying 1) we don't know, and 2)
    > Sun/Oracle doesn't seem to make any such guarantee.
    >
    > I think you are likely to get exactly the same byte codes, but I
    > wouldn't count on it. If your process will absolutely break due to
    > different byte codes, make a more robust process.


    But why would it break anyway? Maybe it's a bad comparison, but I compare
    that to, say, compiling C code with different C compilers or with different
    optimization options of the same compiler. The resulting machine code is in
    no doubt different, but it still does the same thing at the end of the day.
    The one possibility of "breakage" would be for example if you're working
    with some highly memory limited machine (some MCU for example) when with
    some compiler options the resulting machine code would be too large to fit
    inside the machine's memory or it would perform faster or slower (or even
    break your process) with different compiler options..

    However, I can't see a similar situation happening with Java. In other
    words, I don't see the importance of thinking about that stuff when working
    with Java. So my question to Julien is: why do you care about it?
    Screamin Lord Byron, Jan 7, 2011
    #4
  5. On 01/07/2011 12:05 PM, Screamin Lord Byron wrote:
    > On Thu, 06 Jan 2011 15:24:34 -0800, markspace wrote:
    >
    >> On 1/6/2011 3:05 PM, Julien ÉLIE wrote:
    >>
    >>> Suppose I have test.java and I want to compile it with Java SE 6 Update
    >>> 23 on different OSes and hardwares; would it generate the same
    >>> test.class file ("the same" means that it is exactly the same file --
    >>> same MD5 checksum for instance).

    >>
    >>
    >> I think everyone has consistently been saying 1) we don't know, and 2)
    >> Sun/Oracle doesn't seem to make any such guarantee.
    >>
    >> I think you are likely to get exactly the same byte codes, but I
    >> wouldn't count on it. If your process will absolutely break due to
    >> different byte codes, make a more robust process.

    >
    > But why would it break anyway? Maybe it's a bad comparison, but I compare
    > that to, say, compiling C code with different C compilers or with different
    > optimization options of the same compiler.


    Comparing the binary output of class files, perhaps for backup purposes
    or something.

    --
    Beware of bugs in the above code; I have only proved it correct, not
    tried it. -- Donald E. Knuth
    Joshua Cranmer, Jan 7, 2011
    #5
  6. "Screamin Lord Byron" <> wrote in message
    news:1p61343a7cifa$.1a6oua658easw$...
    > On Thu, 06 Jan 2011 15:24:34 -0800, markspace wrote:
    >
    >> On 1/6/2011 3:05 PM, Julien ÉLIE wrote:
    >>
    >>> Suppose I have test.java and I want to compile it with Java SE 6 Update
    >>> 23 on different OSes and hardwares; would it generate the same
    >>> test.class file ("the same" means that it is exactly the same file --
    >>> same MD5 checksum for instance).

    >>
    >>
    >> I think everyone has consistently been saying 1) we don't know, and 2)
    >> Sun/Oracle doesn't seem to make any such guarantee.
    >>
    >> I think you are likely to get exactly the same byte codes, but I
    >> wouldn't count on it. If your process will absolutely break due to
    >> different byte codes, make a more robust process.

    >
    > But why would it break anyway? Maybe it's a bad comparison, but I compare
    > that to, say, compiling C code with different C compilers or with
    > different
    > optimization options of the same compiler. The resulting machine code is
    > in
    > no doubt different, but it still does the same thing at the end of the
    > day.
    > The one possibility of "breakage" would be for example if you're working
    > with some highly memory limited machine (some MCU for example) when with
    > some compiler options the resulting machine code would be too large to fit
    > inside the machine's memory or it would perform faster or slower (or even
    > break your process) with different compiler options..
    >
    > However, I can't see a similar situation happening with Java. In other
    > words, I don't see the importance of thinking about that stuff when
    > working
    > with Java. So my question to Julien is: why do you care about it?


    Perhaps I'm missing something, but why would you expect that two compilers
    would create the constant pool entries in exactly the same order?
    Mike Schilling, Jan 7, 2011
    #6
  7. On Fri, 7 Jan 2011 18:27:57 -0000, Chris Uppal wrote:

    > Screamin Lord Byron wrote:
    >
    >> In other
    >> words, I don't see the importance of thinking about that stuff when
    >> working with Java. So my question to Julien is: why do you care about it?

    >
    > The OP did state:
    >
    > I ask because I wonder whether two different .class files imply that the
    > .java files from which they were compiled (with the same compiler), are
    > different.
    >
    > Why he (or she?) needs that isn't stated, but it doesn't seem like an
    > implausible or unreasonable problem to want to solve.
    >
    > -- chris


    If that's the case then reverse question must be asked too. Whether two
    exactly same .class files imply that the .java files from which they were
    compiled (with the same compiler) are the same.

    Let's say we have:

    public class Test {
    public static void main(String[] args) {
    new Test().loop();
    }
    public void loop() {
    int i=0;
    for(;i<10;i++);
    }
    }

    and:

    public class Test {
    public static void main(String[] args) {
    new Test().loop();
    }
    public void loop() {
    int i=0;
    while(i<10) i++;
    }
    }

    These two sources are obviously not the same, yet the resulting bytecodes
    are.
    Screamin Lord Byron, Jan 7, 2011
    #7
  8. "Julien ÉLIE" <> wrote in message
    news:...
    > Hi Joshua,
    >
    >>> So my question to Julien is: why do you care about it?

    >>
    >> Comparing the binary output of class files, perhaps for backup
    >> purposes or something.

    >
    > The reason why I ask is that I have all the compiled classes of a
    > software. Well tested and it works fine.
    > Then, I was given the source code.
    > I want to make sure the source code actually corresponds to the software I
    > have already tested.
    >
    > When I compile it myself (with the same compiler that was used for the
    > initial compilation), I obtain different Java bytecode (all the classes
    > are different).
    > I therefore wonder how I can make sure the source code is the right one...


    You could try running javap over both sets of class files. If you see any
    differences in the declarations of fields, methods, constructors, etc. they
    don't match. (No help if the only changes are to code within method
    implementations, alas.)
    Mike Schilling, Jan 7, 2011
    #8
  9. Lew

    markspace Guest

    Re: Compiler program platform-independant [sic] ?

    On 1/7/2011 11:07 AM, Julien ÉLIE wrote:

    > The reason why I ask is that I have all the compiled classes of a
    > software. Well tested and it works fine.



    > Then, I was given the source code.
    > I want to make sure the source code actually corresponds to the software
    > I have already tested.



    You'll need to run the test suite against the new code you compiled, and
    verify that the tests run identically. If not, then you have bad bits.

    This is called "regression testing."


    P.S. "Independent" doesn't have an "a" in it.
    markspace, Jan 7, 2011
    #9
  10. Lew

    markspace Guest

    Re: Compiler program platform-independent?

    On 1/7/2011 11:53 AM, Julien ÉLIE wrote:

    > Of course, but well… it is a huge application and the whole test suite
    > requires weeks to be properly done.



    You should also have a "sparse" test suite that runs much more quickly
    and gives confidence that the app is correct. About 8 hours is good, so
    that a build can be tested overnight.
    markspace, Jan 7, 2011
    #10
  11. Lew

    Arne Vajhøj Guest

    On 07-01-2011 12:05, Screamin Lord Byron wrote:
    > On Thu, 06 Jan 2011 15:24:34 -0800, markspace wrote:
    >> On 1/6/2011 3:05 PM, Julien ÉLIE wrote:
    >>> Suppose I have test.java and I want to compile it with Java SE 6 Update
    >>> 23 on different OSes and hardwares; would it generate the same
    >>> test.class file ("the same" means that it is exactly the same file --
    >>> same MD5 checksum for instance).

    >>
    >>
    >> I think everyone has consistently been saying 1) we don't know, and 2)
    >> Sun/Oracle doesn't seem to make any such guarantee.
    >>
    >> I think you are likely to get exactly the same byte codes, but I
    >> wouldn't count on it. If your process will absolutely break due to
    >> different byte codes, make a more robust process.

    >
    > But why would it break anyway? Maybe it's a bad comparison, but I compare
    > that to, say, compiling C code with different C compilers or with different
    > optimization options of the same compiler. The resulting machine code is in
    > no doubt different, but it still does the same thing at the end of the day.
    > The one possibility of "breakage" would be for example if you're working
    > with some highly memory limited machine (some MCU for example) when with
    > some compiler options the resulting machine code would be too large to fit
    > inside the machine's memory or it would perform faster or slower (or even
    > break your process) with different compiler options..


    You forget about implementation specific behavior.

    Java does not have much of that, but C has!

    Arne
    Arne Vajhøj, Jan 7, 2011
    #11
  12. Lew

    Arne Vajhøj Guest

    On 07-01-2011 14:07, Julien ÉLIE wrote:
    >>> So my question to Julien is: why do you care about it?

    >>
    >> Comparing the binary output of class files, perhaps for backup
    >> purposes or something.

    >
    > The reason why I ask is that I have all the compiled classes of a
    > software. Well tested and it works fine.
    > Then, I was given the source code.
    > I want to make sure the source code actually corresponds to the software
    > I have already tested.
    >
    > When I compile it myself (with the same compiler that was used for the
    > initial compilation), I obtain different Java bytecode (all the classes
    > are different).
    > I therefore wonder how I can make sure the source code is the right one...


    That is a actual a common scenario.

    But I think the common solution is to require not just the source
    but the actual build to be the same.

    Exact same jar files.

    Arne
    Arne Vajhøj, Jan 7, 2011
    #12
  13. Lew

    Arne Vajhøj Guest

    On 07-01-2011 13:17, Mike Schilling wrote:
    > "Screamin Lord Byron" <> wrote in message
    > news:1p61343a7cifa$.1a6oua658easw$...
    >> On Thu, 06 Jan 2011 15:24:34 -0800, markspace wrote:
    >>> On 1/6/2011 3:05 PM, Julien ÉLIE wrote:
    >>>> Suppose I have test.java and I want to compile it with Java SE 6 Update
    >>>> 23 on different OSes and hardwares; would it generate the same
    >>>> test.class file ("the same" means that it is exactly the same file --
    >>>> same MD5 checksum for instance).
    >>>
    >>>
    >>> I think everyone has consistently been saying 1) we don't know, and 2)
    >>> Sun/Oracle doesn't seem to make any such guarantee.
    >>>
    >>> I think you are likely to get exactly the same byte codes, but I
    >>> wouldn't count on it. If your process will absolutely break due to
    >>> different byte codes, make a more robust process.

    >>
    >> But why would it break anyway? Maybe it's a bad comparison, but I compare
    >> that to, say, compiling C code with different C compilers or with
    >> different
    >> optimization options of the same compiler. The resulting machine code
    >> is in
    >> no doubt different, but it still does the same thing at the end of the
    >> day.
    >> The one possibility of "breakage" would be for example if you're working
    >> with some highly memory limited machine (some MCU for example) when with
    >> some compiler options the resulting machine code would be too large to
    >> fit
    >> inside the machine's memory or it would perform faster or slower (or even
    >> break your process) with different compiler options..
    >>
    >> However, I can't see a similar situation happening with Java. In other
    >> words, I don't see the importance of thinking about that stuff when
    >> working
    >> with Java. So my question to Julien is: why do you care about it?

    >
    > Perhaps I'm missing something, but why would you expect that two
    > compilers would create the constant pool entries in exactly the same order?


    He seems to be talking about exact same version of SUN/Oracle javac
    just on different platforms.

    I can not see why that code should not generate the constant
    pool entries in the same order.

    Arne
    Arne Vajhøj, Jan 7, 2011
    #13
  14. Lew

    Lew Guest

    Julien ÉLIE wrote:
    > The reason why I ask is that I have all the compiled classes of a
    > software.  Well tested and it works fine.
    > Then, I was given the source code.
    > I want to make sure the source code actually corresponds to the software
    > I have already tested.
    >
    > When I compile it myself (with the same compiler that was used for the
    > initial compilation), I obtain different Java bytecode (all the classes
    > are different).
    > I therefore wonder how I can make sure the source code is the right one....
    >


    Perhaps one was run with "-g" and the other not? Perhaps the "-
    source" or "-target" options differed?

    How exactly do the bytecodes differ between the two compilations?

    Do they decompile the same?

    --
    Lew
    Lew, Jan 7, 2011
    #14
  15. Lew

    Arne Vajhøj Guest

    On 07-01-2011 13:31, Screamin Lord Byron wrote:
    > On Fri, 7 Jan 2011 18:27:57 -0000, Chris Uppal wrote:
    >> Screamin Lord Byron wrote:
    >>> In other
    >>> words, I don't see the importance of thinking about that stuff when
    >>> working with Java. So my question to Julien is: why do you care about it?

    >>
    >> The OP did state:
    >>
    >> I ask because I wonder whether two different .class files imply that the
    >> .java files from which they were compiled (with the same compiler), are
    >> different.
    >>
    >> Why he (or she?) needs that isn't stated, but it doesn't seem like an
    >> implausible or unreasonable problem to want to solve.

    >
    > If that's the case then reverse question must be asked too. Whether two
    > exactly same .class files imply that the .java files from which they were
    > compiled (with the same compiler) are the same.
    >
    > Let's say we have:
    >
    > public class Test {
    > public static void main(String[] args) {
    > new Test().loop();
    > }
    > public void loop() {
    > int i=0;
    > for(;i<10;i++);
    > }
    > }
    >
    > and:
    >
    > public class Test {
    > public static void main(String[] args) {
    > new Test().loop();
    > }
    > public void loop() {
    > int i=0;
    > while(i<10) i++;
    > }
    > }
    >
    > These two sources are obviously not the same, yet the resulting bytecodes
    > are.


    That is also a question that can be asked.

    But in the context of whether what is tested and what
    is deployed is identical, then it is not so relevant.

    Arne
    Arne Vajhøj, Jan 8, 2011
    #15
  16. On Fri, 07 Jan 2011 20:31:40 -0500, Arne Vajhøj wrote:

    > On 07-01-2011 13:31, Screamin Lord Byron wrote:
    >> On Fri, 7 Jan 2011 18:27:57 -0000, Chris Uppal wrote:
    >>> Screamin Lord Byron wrote:
    >>>> In other
    >>>> words, I don't see the importance of thinking about that stuff when
    >>>> working with Java. So my question to Julien is: why do you care about it?
    >>>
    >>> The OP did state:
    >>>
    >>> I ask because I wonder whether two different .class files imply that the
    >>> .java files from which they were compiled (with the same compiler), are
    >>> different.
    >>>
    >>> Why he (or she?) needs that isn't stated, but it doesn't seem like an
    >>> implausible or unreasonable problem to want to solve.

    >>
    >> If that's the case then reverse question must be asked too. Whether two
    >> exactly same .class files imply that the .java files from which they were
    >> compiled (with the same compiler) are the same.

    <...>
    > That is also a question that can be asked.
    >
    > But in the context of whether what is tested and what
    > is deployed is identical, then it is not so relevant.


    Yes, you're right. I was unaware of Julien's updated explanation in the
    time of posting that post.
    Screamin Lord Byron, Jan 8, 2011
    #16
  17. Lew

    Lew Guest

    Julien ÉLIE wrote:
    > It is what is currently shipped. But as we need to add new functionalities to
    > the program, and fix a few bugs, we have to make sure we do it against the
    > right source code (previously, we had both compiled code and what was supposed
    > to be the source code of it -- we did not try to rebuild it).


    Much more important is to fix your broken process that leaves you wondering
    what source code belongs to what release. No amount of retroactive analysis
    will substitute for not screwing up in the first place. Until you get your
    process straight, you are a calamity brewing.

    Haven't you guys ever heard of source-code version control and a managed
    build/deployment process?

    It is horrendously irresponsible to ship code for which you don't know where
    the source code is. Shame on your organization!

    --
    Lew
    Ceci n'est pas une pipe.
    Lew, Jan 8, 2011
    #17
  18. Re: Compiler program platform-independent?

    On Sat, 08 Jan 2011 18:56:19 +0100, Julien ÉLIE wrote:

    Every shipping was versioned (CVS). (I know
    > the process of not rebuilding is bad but that's what happened years ago,
    > and it is not the subject of this thread.) As I said above, focus was
    > done on binaries owing to the software basically being a "business
    > software".
    >

    Was every binary release accompanied by its source?

    I though you were saying that it wasn't, but this mention of CVS versions
    has confused me.

    > I believe the previous maintenance was properly done and the external
    > maintainer deployed the shipped source code. But you know, better check
    > twice -- we're never enough certain in computer science, and always a
    > bit suspicious, never trust anyone *huh* -- so before going on, it is
    > something we wanted to ascertain. It would have prevented us from
    > running the whole testing scenarii (both technical and functional
    > parts).
    >

    I think that all you can do is to bring the latest source code you have
    under version control unless, of course, they passed the complete CVS
    repository to you. Then merge your local changes into the main branch,
    compile the result and do integration and system testing from scratch.

    Did you receive a set of regression tests along with source code? If not,
    can you get them and are they consistent with the system documentation?

    Do you have the system documentation and has it been maintained as the
    system evolved?

    Otherwise, you'd be well advised to write a set regression tests from the
    design documentation, always assuming that exists, and use that to verify
    all aspects of system operation. It may seem like a needless expense now,
    but doing this will save huge amounts of time and effort in future.

    This isn't a swipe at your organisation - just a reflection of my own
    past experience where all too often documentation of old systems has
    either been lost or was so out of date as to be useless.


    --
    martin@ | Martin Gregorie
    gregorie. | Essex, UK
    org |
    Martin Gregorie, Jan 8, 2011
    #18
  19. Lew

    Daniel Pitts Guest

    Re: Compiler program platform-independent?

    On 1/7/2011 12:06 PM, markspace wrote:
    > On 1/7/2011 11:53 AM, Julien ÉLIE wrote:
    >
    >> Of course, but well… it is a huge application and the whole test suite
    >> requires weeks to be properly done.

    >
    >
    > You should also have a "sparse" test suite that runs much more quickly
    > and gives confidence that the app is correct. About 8 hours is good, so
    > that a build can be tested overnight.
    >

    Also, a good practice is to have unit tests for each module of the
    application. The unit tests should be fast enough that you can actually
    re-run them after making a few minor changes. This ensures that the
    program remains stable during changes.

    Now, it sounds more like you've inherited the source code. It might take
    a while, but if you plan on utilizing this codebase for more than a
    month, creating unit tests after the fact wouldn't be a bad idea.

    --
    Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
    Daniel Pitts, Jan 10, 2011
    #19
  20. Re: Compiler program platform-independent?

    Julien ÉLIE <> wrote:
    > And here we are: how can we make sure the source code is the right one?
    > It is a legitimate initial interrogation :)


    By the time that this thread is alive, I wonder if you've already tried
    rebuilding (fully) from the sources, and determined, how many class-files
    are really (binary-)different.

    Were that:
    - nearly all (If so, then I'd rather expect a compiler-mismatch)
    - none (equal class files imply at least equivalent sources)
    - a few (check them with your jdk's javap or any other disassembler)
    - too many to check individually (create scripts for comparison of
    disassemblies)

    PS: I skipped over parts of this thread, so apologies, if I missed either
    an "already solved" or an equivalent to mine post.
    Andreas Leitgeb, Jan 11, 2011
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Gustavo De la Espriella

    How to make an application Database independant

    Gustavo De la Espriella, Feb 3, 2005, in forum: ASP .Net
    Replies:
    5
    Views:
    455
    Matt Berther
    Feb 8, 2005
  2. jcc
    Replies:
    15
    Views:
    4,698
    Nigel Wade
    May 12, 2006
  3. Coca
    Replies:
    15
    Views:
    640
    Alan Balmer
    Jan 14, 2004
  4. Nicky Kotze
    Replies:
    2
    Views:
    344
  5. gga
    Replies:
    1
    Views:
    289
    Daniel Berger
    Mar 8, 2005
Loading...

Share This Page