MappedReadBuffer.java revision 2224:2a8815d86b93
11573Srgrimes/*
21573Srgrimes * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
31573Srgrimes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
41573Srgrimes *
51573Srgrimes * This code is free software; you can redistribute it and/or modify it
61573Srgrimes * under the terms of the GNU General Public License version 2 only, as
71573Srgrimes * published by the Free Software Foundation.  Oracle designates this
81573Srgrimes * particular file as subject to the "Classpath" exception as provided
91573Srgrimes * by Oracle in the LICENSE file that accompanied this code.
101573Srgrimes *
111573Srgrimes * This code is distributed in the hope that it will be useful, but WITHOUT
121573Srgrimes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
131573Srgrimes * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
141573Srgrimes * version 2 for more details (a copy is included in the LICENSE file that
151573Srgrimes * accompanied this code).
16249808Semaste *
171573Srgrimes * You should have received a copy of the GNU General Public License version
181573Srgrimes * 2 along with this work; if not, write to the Free Software Foundation,
191573Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
201573Srgrimes *
211573Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
221573Srgrimes * or visit www.oracle.com if you need additional information or have any
231573Srgrimes * questions.
241573Srgrimes */
251573Srgrimes
261573Srgrimes
271573Srgrimes/*
281573Srgrimes * The Original Code is HAT. The Initial Developer of the
291573Srgrimes * Original Code is Bill Foote, with contributions from others
301573Srgrimes * at JavaSoft/Sun.
311573Srgrimes */
321573Srgrimes
331573Srgrimespackage jdk.test.lib.hprof.parser;
341573Srgrimes
351573Srgrimesimport java.io.IOException;
3692986Sobrienimport java.io.RandomAccessFile;
3792986Sobrienimport java.nio.MappedByteBuffer;
381573Srgrimesimport java.nio.channels.FileChannel;
3971579Sdeischen
401573Srgrimes/**
411573Srgrimes * Implementation of ReadBuffer using mapped file buffer
421573Srgrimes *
43176628Sjhb * @author A. Sundararajan
441573Srgrimes */
451573Srgrimesclass MappedReadBuffer implements ReadBuffer {
46176629Sjhb    private MappedByteBuffer buf;
4771579Sdeischen    private RandomAccessFile file;
4871579Sdeischen
491573Srgrimes    MappedReadBuffer(RandomAccessFile file, MappedByteBuffer buf) {
501573Srgrimes        this.file = file;
511573Srgrimes        this.buf = buf;
52249810Semaste    }
531573Srgrimes
5471579Sdeischen    /**
5571579Sdeischen     * Factory method to create correct ReadBuffer for a given file.
561573Srgrimes     *
571573Srgrimes     * The initial purpose of this method was to choose how to read hprof file for parsing
581573Srgrimes     * depending on the size of the file and the system property 'jhat.disableFileMap':
591573Srgrimes     * "If file size is more than 2 GB and when file mapping is configured (default),
601573Srgrimes     * use mapped file reader".
611573Srgrimes     *
6256698Sjasone     * However, it has been discovered a problem with this approach.
631573Srgrimes     * Creating java.nio.MappedByteBuffer from inside the test leads to hprof file
641573Srgrimes     * is locked on Windows until test process dies since there is no good way to
651573Srgrimes     * release this resource.
66176628Sjhb     *
67176628Sjhb     * java.nio.MappedByteBuffer will be used only if 'jhat.enableFileMap' is set to true.
68176628Sjhb     * Per default 'jhat.enableFileMap' is not set.
69176628Sjhb     */
70176628Sjhb    static ReadBuffer create(RandomAccessFile file) throws IOException {
71176628Sjhb        if (canUseFileMap()) {
72176628Sjhb            MappedByteBuffer buf;
73176628Sjhb            try {
74178427Sjhb                FileChannel ch = file.getChannel();
75176628Sjhb                long size = ch.size();
76176628Sjhb                buf = ch.map(FileChannel.MapMode.READ_ONLY, 0, size);
77176628Sjhb                ch.close();
78176628Sjhb                return new MappedReadBuffer(file, buf);
791573Srgrimes            } catch (IOException exp) {
801573Srgrimes                exp.printStackTrace();
811573Srgrimes                System.err.println("File mapping failed, will use direct read");
821573Srgrimes                // fall through
831573Srgrimes            }
841573Srgrimes        } // else fall through
851573Srgrimes        return new FileReadBuffer(file);
861573Srgrimes    }
871573Srgrimes
881573Srgrimes    /**
891573Srgrimes     * Set system property 'jhat.enableFileMap' to 'true' to enable file mapping.
901573Srgrimes     */
911573Srgrimes    private static boolean canUseFileMap() {
921573Srgrimes        String prop = System.getProperty("jhat.enableFileMap");
931573Srgrimes        return prop != null && prop.equals("true");
94289863Sache    }
95290110Sache
9682807Sache    private void seek(long pos) throws IOException {
97289863Sache        assert pos <= Integer.MAX_VALUE :  "position overflow";
981573Srgrimes        buf.position((int)pos);
991573Srgrimes    }
100
101    public synchronized void get(long pos, byte[] res) throws IOException {
102        seek(pos);
103        buf.get(res);
104    }
105
106    public synchronized char getChar(long pos) throws IOException {
107        seek(pos);
108        return buf.getChar();
109    }
110
111    public synchronized byte getByte(long pos) throws IOException {
112        seek(pos);
113        return buf.get();
114    }
115
116    public synchronized short getShort(long pos) throws IOException {
117        seek(pos);
118        return buf.getShort();
119    }
120
121    public synchronized int getInt(long pos) throws IOException {
122        seek(pos);
123        return buf.getInt();
124    }
125
126    public synchronized long getLong(long pos) throws IOException {
127        seek(pos);
128        return buf.getLong();
129    }
130
131    @Override
132    public void close() throws Exception {
133        file.close();
134    }
135
136}
137