本文目錄一覽:
- 1、Java函數是否適合將大對象作為參數?尤其高並發的時候?
- 2、如何使用java讀取大對象
- 3、關於JAVA~~~~ 如何將圖片等大對象存入ORACLE中~~求詳解!(代碼)
- 4、jvm默認多大的對象是大對象
Java函數是否適合將大對象作為參數?尤其高並發的時候?
java是傳引用,所以大不大無所謂
只是並發的時候如果你又需要對對象做修改,那就要注意對性能影響可能很大了,這個影響是因為你需要鎖住對象確保線程安全,浪費了cpu資源,而不是因為對象大這個原因,也就是說如果你對象雖然大,但是你線程不會對它進行修改,那性能還是很高的
如何使用java讀取大對象
只用到了readLine()方法,但理所當然任何DataInputStream方法都可以採用。一旦抵達文件末尾,readLine()就會返回一個null(空),以便中止並退出while循環。
關於JAVA~~~~ 如何將圖片等大對象存入ORACLE中~~求詳解!(代碼)
插入圖片/文本(blob /clob)到oracle數據庫(引用)
我們在寫OA的時候經常遇到的問題就是員工圖片檔案的儲存問題,解決這個問題有兩個方法,
1.JSP/html頁面裡面讀取web服務器上的圖片,也就是把圖片放到(上傳)到web 服務器上,然後用html 語句讀取:
img src=” 絕對或相對路徑 ” border=”0″ /
2.就是上傳到數據庫裡面(oracle).關於oracle 數據庫,它支持blob, 和clob, 分別對應着圖片和文本(長字符串)操作
由於性能原因,我們還是要採用第二種方法,而且存到數據庫裡面比較容易管理,是吧?
首先,我們要解決上傳問題,這裡採用普遍使用的apache commons 組件裡面的FileUpload class.
具體步驟如:
DiskFileUpload dfu=new DiskFileUpload();
dfu.setSizeMax(100000000);
dfu.setSizeThreshold(100000);
dfu.setRepositoryPath(“f:\\public”);
try{
List fileItems=dfu.parseRequest(request);
Iterator i=fileItems.iterator();
while(i.hasNext()){
FileItem fi=(FileItem)i.next();
if(!fi.isFormField()){
name=fi.getName();
size=fi.getSize();
if((name==null||name.equals(“”))size==0)
continue;
}
name=fi.getName();
size=fi.getSize();
(InputStream)is=fi.getInputStream();
}
上面的代碼是web服務器接受上傳的代碼,參考文件已經在我上篇寫的上傳文本文件里給出,今天,終於想明白了:
dfu.setRepositoryPath(“f:\\public”); 的意思
原來是轉義字符也就是說\n\t等而要打印反斜杠要用\\,其實這個問題原先已經知道,可是由於經驗沒有寫過圖片上傳處理什麼的,覺得很高深,也很可怕,哈哈,心裡有點畏懼.看來基礎的東西,那怕一點點小細節也很重要,接着還有下面的java IO 問題.剛才讀core java 的時候突然發現在講io的時候特意提醒了這個問題,可是我沒有注意!
通過上面的代碼已經實現文件上傳了.然後,我們要實現JDBC數據源鏈接,目的是要把數據插入到oracle.
Context ctx=new InitialContext();
DataSource ds=(DataSource)ctx.lookup(“jdbc/asdbCoreDS”);
conn=ds.getConnection();
conn.setAutoCommit(false);
關於要import java.sql.* javax.sql.* java.naming.* 不再詳細敘述了
接着根據很有用的一篇文章的提示,插入blob類型一定要先1.插入一個空的
String insert=” insert into uploadpicture “+
” values(?, empty_blob()) ” ;
2.然後找到這個blob的oracle 裡面的游標:
String findCursor=” select content “+
” from uploadpicture “+
” where name=? for update “;
注意這個for update(注意!!!必須加for update,這將鎖定該行,直至該行被修改完畢,保證不產生並發衝突。這裡還是難以理解,先記下來吧)
3.然後再修改
String update=” update uploadpicture “+
” set content=? “+
” where name=? “;
這裡的問號是為PreparedStatement參數處理而寫的!
寫這個程序用到了oracle.sql.BLOB class ,這個類是用來操作BLOB數據類型的
當我們通過ResultSet 對象得到
blob=(BLOB)rs.getBlob(1);
的時候我不知道如何處理了,Blob 是什麼?String, int ,long? 我現在也不明白!估計CSDN上的人也不明白,否則我發個帖子半天沒有人回答,也許是很爛,也許是太簡單了,大家不屑一顧,看來我還要繼續追趕!
不發牢騷了,回到程序里(總覺得自己的發散思維很強,看來寫程序的時候不能這樣,多虧java 是純面向對象語言,如果是過程就麻煩了)
我們如何處理這個blob 呢?回答是,不管它是什麼,直接寫入 BufferedOutputStream out1 =new BufferedOutputStream(blob.getBinaryOutputStream());
這裡是建立了緩衝寫如blob 的流(注意getBinaryOutputStream()已經不被贊成使用了,一定有更優秀的方法替代!),說到流,我到現在還有點暈,類很多,不知道究竟用哪個好!
基礎的東西非常重要,這曾經是我的口頭禪,這裡用到了流的讀入寫和寫入,有些流是從文件或其它位置上讀取字節(如, FileInputStream),有寫流是把字節組合成有用的數據(如, DataInputStream).我們讀取數字的時候,需要首先建議一個FileInpuStream, 然後, 再把該類的對象傳遞給DataInputStream
FileInputStream fin=new FileInputStream(“emp.dat”);
DataInputStream din=new DataInputStream(fin);//把fin傳遞給din
double s=din.readDouble();
默認情況下,流是沒有緩衝的, 如果使用緩衝就是
DataInputStream din=new DataInputStream(
new BufferedInputStream(new FileINputStream(“emp.dat”)));
有了這點理解也很管用,
BufferedOutputStream out1 =new BufferedOutputStream(blob.getBinaryOutputStream());
就是建立一個緩衝寫的對象到blob.注意這裡的out1 不是out,否則程序運行的時候不能打印了temp 數據了!
已經準備好如何寫了, 可是如何讀呢?
BufferedInputStream in=new BufferedInputStream(is);
在我們上傳的時候 (InputStream)is=fi.getInputStream();
讀取圖片為輸入的流.保存為is 對象,然後就用到這裡了,準備好了讀和寫了,我們開始幹活:
int c;
while((c=in.read())!=-1) {out1.write(c);}
in.close();
out1.close();
通過緩衝一個個讀數據,然後一個個寫數據.-1 為文件的末尾,
最後當讀寫完成後我們要關閉讀寫對象!
程序分析就是這樣,以後還要對此問題進行研究,最後還要注意,
%@ page contentType=”image/jpeg;charset=GBK”%
不是
%@ page contentType=”text/html;charset=GBK”%
否則是以文字顯示圖片—亂碼.
這裡研究了上傳圖片到oralce 裡面的程序,關於顯示還要麻煩一點,藉助資料我實現了,明天再研究一下.
//插入上傳圖片到數據庫
%@ page contentType=”text/html;charset=GBK”%
%@ page import=”java.util.*”%
%@ page import=”java.io.*”%
%@ page import=”org.apache.commons.*”%
%@ page import=”org.apache.commons.fileupload.*”%
%@ page import=”java.sql.*”%
%@ page import=”javax.sql.*”%
%@ page import=”javax.naming.*”%
%@ page import=”oracle.sql.*”%
html
head
meta http-equiv=”Content-Type” content=”text/html; charset=GBK”
titlegetPicture.jsp/title
/head
body
%
request.setCharacterEncoding(“GBK”);
String name=null;
long size=0;
Connection conn=null;
String insert=” insert into uploadpicture “+
” values(?, empty_blob()) ” ;
String findCursor=” select content “+
” from uploadpicture “+
” where name=? for update “;
String update=” update uploadpicture “+
” set content=? “+
” where name=? “;
BLOB blob=null;
InputStream is=null;
DiskFileUpload dfu=new DiskFileUpload();
dfu.setSizeMax(100000000);
dfu.setSizeThreshold(100000);
dfu.setRepositoryPath(“f:\\public”);
try{
List fileItems=dfu.parseRequest(request);
Iterator i=fileItems.iterator();
while(i.hasNext()){
FileItem fi=(FileItem)i.next();
if(!fi.isFormField()){
name=fi.getName();
size=fi.getSize();
if((name==null||name.equals(“”))size==0)
continue;
}
name=fi.getName();
size=fi.getSize();
is=fi.getInputStream();
}
Context ctx=new InitialContext();
DataSource ds=(DataSource)ctx.lookup(“jdbc/asdbCoreDS”);
conn=ds.getConnection();
conn.setAutoCommit(false);
//step 1
PreparedStatement ps=conn.prepareStatement(insert);
ps.setString(1, name);
int a=ps.executeUpdate();
if(a0)
out.println(“insert success!”+”br”);
//step 2
ps=conn.prepareStatement(findCursor);
ps.setString(1, name);
ResultSet rs=ps.executeQuery();
while(rs.next())
{
blob=(BLOB)rs.getBlob(1);
out.println(“find cursor success!”+”br”);
out.println(“cursor :”+blob+”br”);
//step 3
ps=conn.prepareStatement(update);
ps.setBlob(1, blob);
ps.setString(2, name);
ps.executeUpdate();
ps.close();
BufferedOutputStream out1 =new BufferedOutputStream(blob.getBinaryOutputStream());
BufferedInputStream in=new BufferedInputStream(is);
int c;
while((c=in.read())!=-1) {out1.write(c);}
in.close();
out1.close();
out.println(“update success!”+”br”);}
conn.commit();
}
catch(SQLException se)
{se.printStackTrace();}
catch(FileUploadException fue)
{fue.printStackTrace();}
%
/body
/html
//顯示數據庫裡面的圖片
%@ page contentType=”image/jpeg;charset=GBK”%
%@ page import=”java.sql.*”%
%@ page import=”javax.sql.*”%
%@ page import=”javax.naming.*”%
%@ page import=”java.io.*”%
%@ page import=”com.sun.image.codec.jpeg.*”%
%@ page import=”javax.imageio.*”%
%@ page import=”java.util.*”%
%@ page import=”java.awt.image.*”%
html
head
meta http-equiv=”Content-Type” content=”image/jpeg; charset=GBK”
titleshowDBImage.jsp/title
/head
body
%
String showImage=” select * “+
” from uploadpicture “+
” where name=´TXC with snow.JPG´ ” ;
Connection conn=null;
BufferedInputStream inputImage=null;
try{
Context ctx=new InitialContext();
DataSource ds=(DataSource)ctx.lookup(“jdbc/asdbCoreDS”);
conn=ds.getConnection();
Statement st=conn.createStatement();
ResultSet rs=st.executeQuery(showImage);
while(rs.next())
{
oracle.sql.BLOB blob=(oracle.sql.BLOB)rs.getBlob(“content”);
inputImage =new BufferedInputStream(blob.getBinaryStream());
/*String name=rs.getString(1);
String content=rs.getString(2);
out.println(name+”br”);*/}
BufferedImage image=null;
image=ImageIO.read(inputImage);
ServletOutputStream sos=response.getOutputStream();
JPEGImageEncoder encoder=JPEGCodec.createJPEGEncoder(sos);
encoder.encode(image);
inputImage.close();
conn.commit();
}
catch(SQLException se)
{se.printStackTrace();
conn.rollback(); }
catch(IOException ie)
{ie.printStackTrace();}
%
/body
/html
jvm默認多大的對象是大對象
jvm默認多大的對象是大對象?對象的內存分配——對象優先在Eden分配
當Eden區沒有足夠空間進行分配時,虛擬機將發起一次Minor GC。

testAllocation()方法中,嘗試分配3個2MB大小和1個4MB大小的對象,在運行時通過-Xms20M、-Xmx20M、-Xmn10M這3個參數限制了Java堆大小為20MB,不可擴展,其中10MB分配給新生代,剩下的10MB分配給老年代。-XX:SurvivorRatio=8決定了新生代中Eden區與一個Survivor區的空間比例是8:1,從輸出的結果也可以清晰地看到“eden space 8192K、from space 1024K、to space 1024K”的信息,新生代總可用空間為9216KB(Eden區+1個Survivor區的總容量)。執行testAllocation()中分配allocation4對象的語句時會發生一次Minor GC,這次GC的結果是新生代6651KB變為162KB,而總內存佔用量則幾乎沒有減少(因為allocation1、allocation2、allocation3三個對象都是存活的,虛擬機幾乎沒有找到可回收的對象)。這次GC發生的原因是給allocation4分配內存的時候,發現Eden已經被佔用了6MB,剩餘空間已不足以分配allocation4所需的4MB內存,因此發生Minor GC。GC期間虛擬機又發現已有的3個2MB大小的對象全部無法放入Survivor空間(Survivor空間只有1MB大小),所以只好通過分配擔保機制提前轉移到老年代去。這次GC結束後,4MB的allocation4對象順利分配在Eden中,因此程序執行完的結果是Eden佔用4MB(被allocation4佔用),Survivor空閑,老年代被佔用6MB(被allocation1、allocation2、allocation3佔用)。

下面看看使用Parallel Scavenge收集器的情況:

沒有發生新生代GC,直接把allocation4分配到老年代上。
對象的內存分配——大對象直接進入老年代——典型的大對象
很長的字符串以及數組
對象的內存分配——大對象直接進入老年代——大對象噩夢
比遇到一個大對象更加壞的消息就是遇到一群“朝生夕滅”的“短命大對象”,經常出現大對象容易導致內存還有不少空間時就提前觸發垃圾收集以獲取足夠的連續空間來“安置”它們。
對象的內存分配——大對象直接進入老年代——原因
大於-XX:PretenureSizeThreshold設置值的對象直接在老年代分配。這樣做的目的是避免在Eden區及兩個Survivor區之間發生大量的內存複製。

PretenureSizeThreshold被設置為3MB(就是3145728,這個參數不能像-Xmx之類的參數一樣直接寫3MB),因此超過3MB的對象都會直接在老年代進行分配。
PretenureSizeThreshold參數只對Serial和ParNew兩款收集器有效,Parallel Scavenge收集器不認識這個參數,Parallel Scavenge收集器一般並不需要設置。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/231677.html